What's wrong with Unity?

Introduction

And I mean besides the whole licensing change thing that happened this year, and that they went back on, because obviously it was stupid, and management didn't listen to the people who told them it was stupid, and pushed for it anyway, and got a ton of well deserved shit for it.

These are some of my thoughts after working with unity for a few years almost every day, both at my actual day job and on some other projects. I don't think many of these things can be fixed without much effort by them, that they won't do, because it does not bring them more money. This leads us nicely to the first point I want to make:

The focus on the features that don't matter

Have you ever read the official unity blog? It feels like every time I open that page, the latest article is something I as a developer do not care about in the slightest. You're adding support for mobile browsers? I don't care, I don't make mobile games. You added some "next-gen" AI bullshit to the engine as a package? I really don't care, I'd rather hand craft everything, and have a real artist make the art, and learn blender to make 3D models, and write an actual connected story myself, or have an actual writer do that. But I'm sure the investors care about it, it's the current big thing.

The other thing they have been pushing for a while is AR, which I never understood the actual purpose of for a game engine. I don't think I've ever seen an AR "game" that worked well and didn't look out of place. It feels to me like the techology has not progressed since the time of the New 3DS (which had AR cards that would show you funny 3D models of characters. And going through all of those took like half an hour tops).

And whatever else next thing they push, despite the actual engine and editor having so many things that could be improved. Instead, they prefer to create another half-baked new feature to chase after a trend. I don't think I was ever excited for something they added in a new version. Since 2019 the most exciting thing for me was when they updated their C# runtime to actually support modern C# versions, that was nice. As to the things that could be improved…

The editor itself

It is so, so painfully slow. Why is it so slow? Everything takes time even on a modern PC with a fast SSD. Maybe that's a me issue, but I have heard similar complaints from other people. Sometimes a new version makes things not as slow, but at my job I really hate having to wait for 5-10 seconds after I change a line of code for it to recompile, reload, update the assets, and whatever else it's doing. Why can other engines have a responsive interface and compile times that don't completely stop your work flow for 10 seconds and unity can't? I'm not sure. Maybe it's the C# runtime, maybe it's because it checks the entire project every time. Even for smaller projects it still takes a fair bit longer than I'd like.

Actually, why are they using C# at all for a game engine? I don't think this is a very popular opinion, but I feel like C# does not fit very well into something that requires, preferably, no pauses for garbage collection and little to no constant garbage allocation. You have to work around the language a lot of the time, like making sure to pool your objects, and not create too many strings, and not use C# events and static fields because they live outside the engine and unity can't control them, so if your object gets destroyed that stuff now has dangling references to dead objects and will break things. And the compile times, again. It just takes so long on big projects, is there really no solution to this issue? And the whole IL2CPP thing, too, that blows up the already long project build time tenfold in terms of both RAM and time, that just transpiles the whole project to C++. It's an interesting solution and arguably helps with performance in the compiled game, but it takes so long. And by now I don't have enough RAM in my PC to build the project locally (currently I have 34GB installed and that's still not enough for it most of the time, unless I close every single other program on my computer).

The custom editors and serialization

The custom editors. It's a great idea but it is a very bad implementation. The whole immediate mode GUI thing that is not connected at all to how you build the UI in game (which is a topic I will mention again later) and that you have to constantly work around if you want to do something slightly out of the ordinary, because it's oriented on using their terrible "SerializedProperty" system which only allow access to a hard coded substet of types that unity has arbitrarily decided upon. And it also breaks every single major release. I don't remember updating unity without a custom editor breaking in some stupid way, like text suddenly being the wrong size, or the "open folded property" button being inside of the text instead of on the left of it, or one of the properties just deciding that it's of a different size now and being moved into the middle of the big textbox above it, or letters in that big textbox just collapsing into echh other. Really, "hard coded substet of X unity has arbitrarily decided upon" seems to be a reoccuring thing. You want a serialized function? Only zero or one arguments, or it won't work. You want a nested list? No, wrap each of the nested lists in a class, or it won't work. You want a dictionary? Just straight up does not exist. Use two lists as keys and values. You want polymorphism? Well, there's SerializeReference, but it doesn't have a proper UI to create instances of the polymorphic classes, so you better write a custom editor for that one. Also, if the name/namespace of your class changes, it will break. This is really the only thing that breaks if you rename a class properly (which means also renaming the meta file, since everything else actually uses its meta ID, it's just THIS thing that uses the actual full class name), and sure there's an annotation to fix the renames but was it really that difficult to just make it work? Sure, alternative solutions exist, and they have solved all of these issues a long time ago, but why the hell is the built in solution so bad?

As a comparison, godot's editors are just normal UI nodes. In fact, the whole godot editor is just normal UI nodes. And their serialization system actually has dictionaries and polymorphism built-in, and functions with any number of arguments. Hell, you can even bind or unbind certain arguments in editor and then add more when calling the function. It's actually insane how much better both of these things are compared to unity's broken system. I'm sure if Unity wanted, the could make all of these things work, it's just that their priorities are ad techologies and AI "innovation".

The animation system

The whole animation system. Why the hell are animation events so limited? Once again it has been arbitrarily decided that you can only call functions, and that these functions have the the restrictions as mentioned above of "zero or one parameter". And the editor for that whole thing is just atrocious. Why can't I reorder events that are on the same frame without doing an acrobatic fucking pirouette of moving it to another frame to the left if I want to move the event before the others or to the right if I want it to the right of the others; and if I want it in the middle? Well, do the same thing with all other events that are after or before it, depending on which is faster to rearrange. Godot was able to do it just fine, they have events of arbitrary types and arbitrary properties and even different interpolation types. I'm not actually sure if unity can do anything beside linear interpolation and curves. Also, why not just let me type out the property I want to animate, or at least allow me to search for the game object, or the property on the object? You really have to manually open the whole hierarchy each time in the tiny selection window and browse to the property you want to animate, and then remove the parts you don't want to touch like RGB in the Color type when I just want to change the alpha.

The asynchronous programming

It actually baffles me how bad it is with the whole "asynchronous queue" which is actually very much synchronous, just in another thread. If you try to load two things, they won't actually load in parallel or anything like that, and if you, Dog forbid, try to load a scene without instantly activating it, that will stop the whole queue until you activate the scene. Also, no canceling the loading of the scene. And they built the whole "addressables" system on top of that, so it still doesn't solve the issues of "loading a part of the world where the player may go next without activating it and causing a spike of Awake calls". In fact, I don't think there's any way in Unity to do that short of having your own life cycle for objects so they don't immediately activate all in one frame after scene loading. You can theoretically work around this by having your scenes as prefabs instead, these can in fact be loaded and activated later, but it's a different editor than scenes and half of the things that work with scenes don't work with prefabs when they're loaded like that (static batching at runtime, for example, unless you manually call that on the prefab yourself, which by the way uses FindObjects to get every single object currently in the running game, then runs a for loop on all of them to see if they're a child of a parent you passed into the function, and then uses LINQ to copy that entire array but now make it sorted. If you ever have the time, you may have some fun by decompiling StaticBatchingUtility.Combine and reading through the shit they do in there). And also, no rearranging children and having a preview of the actual game world in prefabs, et cetera. Why did they even have Scenes and Prefabs as separate things? Other engines just have them be the same thing and it works just fine. They're the same fucking thing, Unity.

The UI system

I have no idea how people build UIs with that garbage. The components it has are very basic and the layouting capabilities are just not reliable at all, I am still to figure out how to make the UI in unity look any good without just using sprites for everything and disregarding their components. Sure, there's some new "UI elements" thing, which still has almost zero built in components and the "recommended" UI system is stil the atrocious barely working old one. And even with the whole UI elements thing, I'm not sure I want to write HTML and CSS for a game's UI after my experience with WPF (which I hear some people like, but I am not one of those people). Also, the default styling for them is just straight up bad and half of the built-in components are actually other components stacked in a weird way that kind-of-barely-works but the styling clashes and you have to replace all of it anyway, like the scroll box (which by the way has no way to scroll to an element in it built-in, you have to also code that one youself. Was it really that difficult to just make a normal scroll component with basic features and not "let's pretend that masking child content outside of boundaries of this component and moving the child up and down is actually scrolling").

Unity is not a 2D engine

They love to pretend that it is sometimes, but the lack of actual 2D components is just stupid. For the longest time there was just no way at all to have lighting in 2D, though I hear that's been solved a little bit ago finally. There are no 2D particles, there is no 2D pathfinding, all the coordinates of all the objects are still a Vector3, at least the damn physics system is an actual 2D physics system (Box2D, what else could it be?), that would have been even more embarassing if they got that wrong, and they have 2D collisions "kind of" but they're not as advanced as 3D and have separate callbacks (Why? It doesn't make sense to have an object collide in both 2D and 3D anyway. Probably because they couldn't figure out a good type for it or something). The audio attenuation still works in 3D so if your camera is too far from the 2D world you won't hear anything. Then again, the audio system in unity is also just not very good, better use FMOD if you can. At least they have various audio effects if you want them and can't affort FMOD. Can't vouch for the quality of those, did not have to use them much. Also, while not a 2D issue per se, why the hell is there no built-in tweening solution? I don't want to use the idiotic animation system to show a menu slide in, and what if the position is dynamic? There's a great package called "DOTween", and it solves this problem, but why the hell is it not built in? I feel like animation is one of the very important parts that a game engine should provide, especially for 2D games which (sometimes, not always) tend to be more UI heavy and would benefit greatly from an easy way to animate all of that.

(Update: 14 Feb 2024) No file selection dialogue

Unity does not and never had a built in way to show a file selection dialogue in a running game. There are, as usual, plugins that kind of work. You can also manually copy a mono Windows Forms DLL file and use the ugly Windows Forms file selection dialogue, but I'm not sure if this works anywhere but on windows, so you probably will need to create some kind of workaround for every system yourself or use the aforementioned plugin.

Thing is, unity has a file selection dialogue for the editor, it's in EditorUtility. It works on every system, too. So why not add the same thing to the built standalone player? Is it really that difficult? I don't think it is. Hell, they could make their own system-independant file selection dialogue. Godot did that, and it works fine. That one even works in browsers (with the virtual filesystem, which is a bit different, but still).

(Update: 28 Feb 2024) Advanced search

Did you know unity has advanced search that can filter things in the scene or in the project by various things, and even by the values of properties, I have always thought this would be nice and turns out it does exist (with caveats, the property filter is very basic, like everything unity does. Honestly, is it really that difficult to add things like arrays into this filter?). This is a really cool feature that's never ever advertised or used by anyone I know, and the only way to access it is to press Ctrl+K, I don't even remember where I learned this.

However, there is a very big issue with it that makes it not really usable for me: if there are a lot of results it will crash the progam because it takes too much memory. It's not even a normal unity crash where it asks to submit a crash report, it will just hang up after searching for some time and then hard-close the program with no message. I tried searching for meshes in the whole project and it happened 2 times after a little bit of waiting. Come on, couldn't there be some kinda limit on it or something? I have 34G of RAM, and I still run out of memory a lot. And every time it happens, it's always Unity.

Conclusion

I probably forgot something else, in which case I might update this article later. These are the things that come to mind when I use any other engine and think "I wish unity had this, this is so much better". But Unity is not a game development company, they don't actually use their own engine. If they did, it wouldn't be so bad, I'm sure. They're an ad company, they're a making huge cash money and pleasing the investors company. So what goes in the engine is whatever gives them more money, it seems like. And not the things people have been begging them to add for the last 10 or whatever years. Just use a different engine. Especially if you're making a 2D game. DO NOT USE UNITY FOR 2D GAMES. Use ANYTHING else:

GameMaker recently became free and they're actually adding new useful features to the engine, it looks like (and you need to just pay them 100$ once if you want to sell your game now instead of some stupid subscription that they had before). But also look at this stupid stunt they pulled in 2012 and think what you will about that.

RPGMaker MV/MZ is arguably not a great engine, but since it's javascript you can literally go inside the engine and change the parts you don't like; It's very easy to get started with these two.

Defold, this one uses Lua (which is for sure better than C# for games), and I've heard some nice things about it before, plus it's open source. Want to try that one myself at some point. Apparently it can do 3D too, might be interesting to look at.

Godot is probably my favourite from these, and you can do 3D games in it too, in fact it seems pretty alright for 3D games. I've been using it for about a year now and sure it has issues, especially with the editor stability, but it starts up in like a second and reloading code changes is instant. And they have a programming language specifically designed by them for making games. Seriously, try it.

I've been meaning to gather everything I dislike about unity in a single post for a while, and this is the result. It's getting a bit late now, so I'll probably go to bed after publishing this. Goodnight, and thank you for reading my blog post.

Game review: BOOK OF HOURS

Preface

This post was actually written a long while ago, the week the game released. It used to mention that if you buy the game now, you would get the so-called "perpetual edition", which gives you all DLC for free when they come out. The time has passed, as the article never got released on the website it was supposed to be on at the time, so I'm publishing it here instead. It was also supposed to be my first impression of the game, but I have since finished the game, so I expanded on some points compared to the original article.

The game

Book of hours is a new game by Weather Factory, of the Cultist simulator fame, that came out in August of 2023. The game's steam page describes it as "an elegant, melancholy, combat-free crafting RPG set in an occult library, from the creator of Fallen London, Sunless Sea and the double BAFTA-nominated Cultist Simulator". Indeed, unlike their previous game, this one is much more relaxed and does not hurry you along all the time.

If you've played Cultist Simulator previously, you know how stressful that game can be, you always need money to continue paying the bills, and to get money you have to work various jobs almost non-stop, or sell things. Book of hours also features the mechanics of work and money, though this time it's not strictly required to keep playing. You don't need to pay the bills or get food or anything like that, you only spend money to pay people or buy things. Mostly pay people, as you'll be needing a lot of help with how the game's exploration mechanics work.

Unlike Cultist Simulator, you are no longer tied to just a table with cards on it. The game still features cards, and card slots, and aspects, all the same core mechanics, but now there is a map that you have to explore. You start the game washed up on the beach with nothing but a wet book. From there, the game expects you to figure things out yourself: there is no tutorial, no arrows, no message that helps you get started, besides a tip on how to navigate the map. Really, this is all you need to start out: look around the beach, try the different buttons you have available: the lock icon that shows where you can move to a different location (into the town near the beach) and the "consider" button.

Though the game features no tutorial or other help of that sort, many descriptions of cards, aspects, and actions now feature helpful snippets in square brackets that shed some light on the cryptic words in the box itself, and sometimes even tell you where this card can be used (however, this is usually not the only place it can be used in, just the most important one for someone who is just starting out).

Through various actions on the beach, you will get one of several starting parts of the soul that will define how your game starts and what mysteries you will be looking into first. As the game says, there will be more that you can discover later, but first you will need to get into town using some old acquaintance (which one depends on your chosen aspects), get that wet book dry again, and figure out how to get into the library, which you have come to the island to maintain.

As you've likely figured out from your travel from the beach into town, to unlock new locations you will likely need help of other people. It comes in many ways, both from town's inhabitants and the passers-through. Later, you will be able to also boost their abilities with your own, or various items. Unlocking the rest of the town shouldn't be much of an issue if you've gotten through the rest so far, talk with people, ask someone you already know to introduce you, that sort of thing.

From there, you should be able to ask someone from town to help you getting into the library, or as it's called in the game, "The Hush House". When you reach the first room of the house, you'll likely see that it's a huge castle with dozens of rooms that you will be unlocking throughout the game. The basic rule for unlocking them stays the same: you find someone to help you with aspects matching the room's, then you boost their aspects with your own parts of the soul, skills, items, or memories, by discussing these topics with them. Though be careful, as if you don't use their help by dawn, they will leave (as will the memories disappear). There are also a few rooms that are unlocked in a different way, but it's different for each of them and there are just a few.

In the rooms you unlock you will find uncatalogued books. This is the second major new mechanic of the game. You catalogue books, they contain a mystery of some level, you try to study them and match the level of the mystery with your own aspects, and if you are successful, you will learn a lesson from them, which can be made into a skill and put into a special tree that gives you more parts of the soul (this is how you unlock additional ones that you did not choose at the beginning). Skills always go into one of two slots in the tree, which gives you a lot of freedom on which skills you actually want to get. In the release version of the game, this caused issues where certain skill choices would lock you out from upgrading some parts of the soul, as the aspects wouldn't match the workbenches required for upgrades. This has since been patched, and I believe all skills are possible to upgrade just fine. Though there are actually less skills in the game than there are entries in the tree, so it is not possible to upgrade every part of the tree to the maximum.

With the books, the game actually introduces the two mechanics that will hamper your progress: infections and maladies. When you catalogue the book, the game will warn you of the chances the book may be infected: most of the starting books aren't, but there's always some small chance. If you get an infected book, read the description of the infection carefully, and you should be able to understand how it can be removed. If the description says the infection can spread, put the book in a room that doesn't have much of anything else - that way it shouldn't hurt you much. However, if you got unlucky and used the aspect of the soul that the infection can corrupt while cataloguing the book, it will become a malady; another way to get a malady is failing to study a book, so there is a chance the part of the soul you used will instead get corrupted the same way. It can be cured, as the description of the card says, and it cannot be used in many places, but there is also an upside to it: if you use it as effort in the things that allow it, it will not become tired, like normal soul parts.

As far as I know, trying to explore more rooms, catalogue books, and unlock more of the skill tree is the primary game loop. You don't actually need to explore the entire house to finish the game, but I have done so nonetheless, since it's such an interesting and huge place. There's also crafting, which you'll eventually need to create items to help exlore the house or solve mysteries in the books, and recently they've added a catalogue of things you have already crafted so you don't actually have to write it down manually. That said, it is still helpful to do so, as there is no way to see how to craft a specific item you need, just what can be crafted from the skill in the workbench. I highly recommend using some kind of note taking application or steam's built-in notes to write down your recipes, books and such.

It is very enjoyable to explore the game on your own and figure out its mysteries. If you're a fan of cultist simulator, you probably already bought it, and if you're one of the people who haven't played it: maybe you should try that one out too. It's a lot more punishing, but it has its own charm. If being constantly rushed by the game sounds like too much by you, the Book of Hours will definetely be more your speed. Both of the games make you figure things out and experiment in interesting ways. If that's something you're looking for, this is a great game, though the price of 22.49$ may be a bit of a turnoff for some, that price is well worth it.

Love Exalt 8372 release and the things that got us there

Preface

This is a repost of an itch.io post, and only includes my part of it. You may want to read the complete thing, since it also includes something from the game's writer. It's about a game I've been working on with a friend for a bit, and it's out on itch and steam, linked at the end of the post.

The post

Hi, we just recently released and I wanted to talk a bit about how we got this game working. When the idea to actually make a game from the story came to be, we discussed what engine we should choose. At that point, it wasn't exactly clear what kind of game it would be, though we settled quite fast that we should limit the scope of the game to something we could actually make in a reasonable amount of time with such a small team. The engines we thought of at that point were Unity, Godot, Ren'Py, and a custom engine. Custom engine and Unity were the first ones to be scratched off, since a custom engine meant it would likely take a long time to get anything presentable working. Unity, we both agreed, was too big and clunky for what we wanted to make, and, despite me having a lot of experience with Unity, or perhaps because of that, I have grown to dislike working with Unity and its many design flaws. Another proposition was RPGMaker, but we quickly decided that perhaps we didn't actually want a top-down RPG game, since that meant lots of sprite art, and we would've had to slow down the story with RPG gameplay, much like Danganronpa is slowed down by some of its gameplay, although it's a great game at many points.

In the end, we've stopped on Godot; we've never worked with it, so neither of us had much bad to say about it. It seemed like a good general-purpose engine that has good documentation and actual support for 2D games (unlike Unity). Godot is open-source, too, so patches could be made to the engine directly, if need be (and there was indeed a need, at some points). Working with it, we've also noted the quick release cycle they had for Godot 4, which meant that fixes for major issues would usually arrive within a week or sometimes even a few days. Speaking of Godot 4… initially, we tried 3, which is the current stable version, but it seemed to me that 3 lacked a lot of small quality of life things and GDScript language features that they've made available in 4, so early in the development process we made the decision to switch. Of course, since Godot 4 has no stable release yet, we encountered some issues and crashes within the editor and with exporting the game, but all of these issues were resolved within a few days or weeks with the new Godot releases, and we've steadily progressed on the demo up until its release.

We've opted to use Godot's resources system instead of just text files for the game's written content. That was mostly a decision of mine, and I've tried my best to make it as painless as possible to add content to the game by implementing custom resources and inspectors. Overall, there's a lot of clicking on buttons and expanding sub-objects, but it's far from how annoying it was at the start. The idea behind using resources instead of just text files was to make sure that we never had issues with typos in file structure or dialogue navigation. Plus, this meant not having to write a parser for all of that. Seems that this approach is not oft taken, and people do usually opt to make custom formats and parsers, but nevertheless, this is the path we chose; perhaps in the future something will change about our setup, but, for now, we're sticking with it.

Some time before the game's actual release we got the Steam and Itch pages set up. For Steam, things have been mostly smooth, and, after incorporating feedback from Valve, we released our demo. The paid release of the game will feature achievements, too, and the demo's save system will ensure that the achievements will be unlocked automatically when players move from the demo to the paid release. This way, we hope the migration from the demo should be mostly imperceptible, and you can just continue playing like nothing changed. On Itch's part, there was no review up until the game's actual release, at which point we discovered that if your game costs money, Itch won't let it be searched on the site until they've reviewed it. Unfortunately, we're still waiting on that review, so the game can only be accessed from someone's profile or from a direct link. Other than that, we haven't had issues with releasing on Itch either.

For the Steam release, we wanted to have Steam integrations like achievements. Turns out, the library that provides bindings to the Steamworks API, GodotSteam wasn't yet ported to Godot 4. Thankfully, it was fairly little work to do that, and in a few evenings I got it working with Godot's GDExtension and submitted the patch to the library. It was accepted, since it got the library working at least, but it's still not considered stable, because it hasn't been tested that thoroughly— but it should mostly work fine. If you're using Godot 4 and want Steam integration, take a look at it.

Close to the demo's release, when the story was mostly done, we got to work on polishing and fixing bugs that we and our playtesters had found. There were quite a lot of minor issues and some major bugs that slipped through up to that point, but now we've got them fixed, and the demo release should be mostly bug-free. It took a while, and I'd like to thank everyone who played the game and told us about the issues; with the help of those people, we also touched up some parts that didn't make sense to them, like providing a little tutorial at the start of the game which teaches you the main mechanic, but still lets you figure out the rest yourself.

So far this has been an interesting experience, and I like the Godot engine a lot more than Unity. I hope we can continue to have fun making this game and eventually make it a complete story. Thank you for reading this long post and sticking through to the end, and I hope you enjoy, or enjoyed, the demo!

Game thing progress #11, something I never thought I could do

Greetings! It hasn't been that long since the last time, though can't say I've been busy most of that time. Some work is happening for day 5 of the game, but it's not finished yet. It might, once again, be more walking content than all the game combined before, and that does take time. Though on that front I've been somewhat lazy, there is some stuff. But that's not what this post is about, this post is about something I thought would be too complicated to actually do in a reasonable amount of time, but turned out to only take about a week and a lot of patience. That thing is making the game work in the browser.

Now, originally I developed the whole thing using SFML, then I changed the sound system to use SDL, because SFML's sound system did not allow me to statically link in different sound formats or disable the ones I do not need. With SDL, this was possible quite easily.

Since then, I've tried a few times to make the game run in the browser by porting SFML to the browser, but that turned out to be too much for me, since it's a rather complicated library and I'm not particularly good with graphics programming, plus it uses a lot of old GL features not available in WebGL. But there's another multimedia library that has a lot of features but, unlike SFML, can run in the browser. That library is SDL, the one I previously used just to have sounds.

Over the span of about a week, I've replicated the visible interface of SFML that I use, with exactly the same names, with small changes in some places where it was easier to change it than to make my interface compatible. Inside that interface everything actually runs on SDL, or rather SDLgpu, which is a library that allows to easily use shaders with SDL. That way, I didn't have to change most of the actual game code, while getting the benefits of SDL, particularly running in the browser and modern OpenGL/GLSL versions, though I use them rather sparsely since I'm not too good at it.

Particular pains were caused, as usual, by emscripten, which is a library used to compile C++ to something web browsers can run. It's very finicky to get things working there, and you have to turn on a bunch of different compilation flags, change your source code a bit, add some conditional compilation directives where things work differently in the browser. Thankfully, this was not actually my first time porting native games to run on emscripten, there were two other games before, one running OpenFL (written in Haxe programming language), and the other one was actually running SDL, which came in handy a few times, because I already knew what to do since I've done it before. The games themselves shall not be mentioned, I'm sure you'll find them if you know where to look.

For the save system, I've opted to use the "IndexedDB" feature of browsers, which through a library provided by emscripten allows me to save files there like they were actual files on an actual filesystem, and load them on game start afterwards. Though this does not work in private browsing mode, I don't find that too much of a concern for now. I may add a way to export the saved game to a file at some point.

Another source of concern was the fact that when run on itch.io, the game is embedded as an iframe, which causes problems with getting keyboard focus. After a while I figured out that if I add a "on mouse released" event handler to the canvas and make that focus the canvas, it works fine, though I have no idea why this isn't the default behavior, obviously I want to focus it if I'm clicking on it, right?

Anyhow, the game works pretty much in the same way as before, except it runs in browser now. I've also ported my other game (also linked at the end of the post) to this updated version of the engine, and it works rather well. I've turned the resolution change button off in the browser, since it doesn't make much sense, and I've been thinking about maybe implementing some way to change the resolution better instead of the current way of 3 hard-coded resolutions, but I haven't found a good way to do it yet.

So, if you'r reading this, you can now play both games in the browser, so go do it, alright? And thank you for reading my blog post!

Game thing progress #10, the 0.3 release and whatever was inbetween

Hey. Still alive. Haven't been working on the game in a while, doing other things. The 0.3 release was actually ready a while ago, and I wanted to have someone help with rehauling the city part of the game, but that has to wait, so I finally decided to release this version. It adds the next day along with some walking content and important plot points, exciting, I know. The save game is mostly compatible with a minor problem that can't easily be resolved automatically, so if you have an old save file, feel free to message me and I'll fix it for you, but I think everyone forgot what the game was about anyway in two or so years that passed.

So, for some technical details, there's modding support available now that allows you to basically make a standalone game with the engine, which I did for a gamejam (see here). That was pretty fun, took me less than a week since I didn't have to do anything for the engine, pretty much. If you want to use the engine for your projects, message me somewhere and we'll figure something cool out.

For people on linux, the dependency on a bunch of external sound libraries is gone, you don't really need much at all to run the game now, almost everything is bundled. And there are save game slots now, so you an have more than one saved game, though really the game is still not that long, but it's nice to have.

What have I been doing, anyway? Well, I'm done with colledge, been for a while in fact. I actually presented this game's editor and modding capabilities as my diploma project, and got the highest possible grade, so I got to boast about that to everyone. Wrote a torrent tracker in Ada, that one's pretty fun.. Not much people using it, but it's alive and getting some new stuff uploaded and users registered. Played some video games, obviously, Demon Turf was the most recent one, pretty fun platformer, that unfortunately drags a bit too long with its level remixes. Also played a lot of Final Fantasy 14, probably the best MMO around and in general an alright game. Helped some more on that porn game, it's going along somewhat. Got a ebuild into the official gentoo repository, that I update when I can. Elden Ring came out so I played a bit of that, good game. Played a bit of Cruelty Squad at a friend's place, also a very interesting game.

Don't really have much more to say, go play the new version, out NOW!!!! Seriously, the plot thickens and it has some cool new things.

And thank YOU for reading my short blog post!!

General observations about the inner workings of RPG Maker MV, plus tips and such for writing plugins

About RPG Maker MV in general

Since I've been doing some things other then "the game thing" for some time, I've decided to maybe write about it too. Of course, the game is not forgotten. I just struggle to find motivation to do more writing for it, even though the ideas are there. It will be done when the time is right, so let's proceed to the actual theme of this post: me digging through rpg maker mv sources and figuring things out.

Basically, I was given rpg maker mv to help out on a certain game that shall not be mentioned here, since nobody would understand either way. In particular, I was asked to help out on the "plugin" part. What this means: the whole engine is actually written in javascript, unlike the previous versions which, I believe, were written in something else and had ruby for a scripting language. Now since it's written in JS, the whole engine is basically an open box. You can modify anything, the whole thing. They give you the whole engine to mess around with. Except the editor, which is still a separate program, though the editor simply spits out JSON that the engine interprets (so you can also change how it interprets it too).

Now, the developers of rpg maker did something clever: instead of just giving you the engine and saying "yeah you can mess around with it" they added a system of "plugins". In essense, plugins are javascript files that are loaded after the main game. Since they are loaded afterwards, you can then override any part of the engine in your file without touching the actual engine code. Since javascript is prototype-based, simply changine the prototypes overrides the behaviour of the engine, while also leaving the original code intact if you want to use it later.

That said, unfortunately the creators of the engine abandoned it in favor of their new, slightly modified version of it, called rpg maker mz, a few years ago. And are selling mostly the same engine with somewhat improved editor. So no more updates to MV. Though since the whole engine code is available, that's not a big problem. One can make it whatever they want, it's just another 2D game engine that is somewhat steered towards RPG top-down games, but can do just about anything. Hell, you could make a custom editor for its json data system too, and replace their proprietary one.

About plugins and the state of the community

As mentioned before, plugins are the way to modify how things work without actually touching the engine code. An improtant part of plugins are parameters they can receive, and which can have different types to make the editor show different inputs for them. A good/only/official explanation of all the types is available here.

RPG Maker has official forums, and these do have a specific place for plugin discussion, tutorials and other things for each version of the engine. It seems that most people using the forums, except the few veterans who have been using the engine for years, don't have much idea about how plugins work, or about the inner workings of the engine. Since the editor is so good, a lot of the time they don't have to.

Though it is somewhat painful to see people giving clueless suggestions on the forums, with outdated ways of doing things in JS or simply not understanding how it works. Sometimes people say something is impossible to do, even though you have the whole engine source, so really anything can be done with enough effort.

One thing in particular I have noticed, is that nobody uses modern javascript constructs, though they have been available for a while in NW.js (the thing rpg maker mv uses to run on desktop, it's basically a webkit renderer with node for javascript). For example, evreybody seems to use the pre-es6 way of defining classes, simply because that's how they write it in the engine code, because the engine itself was made in pre-es6 times, I believe. So you see things like this (take from here), though admittedly the post is from 2017, ES6 was already available at the time (ES6 came out in 2015):

  function Window_MyWindow() {
      this.initialize.apply(this, arguments);
  }

  Window_MyWindow.prototype = Object.create(Window_Base.prototype);
  Window_MyWindow.prototype.constructor = Window_MyWindow;

  Window_MyWindow.prototype.initialize = function(x, y, width, height) {
      Window_Base.prototype.initialize.call(this, x, y, width, height);
  };

  Window_MyWindow.prototype.refresh = function() {
      this.drawText("This is a test message", 0, 0, this.contentsWidth(), this.lineHeight());
  };

instead of the easier and equivalent way of doing the same thing in ES6:

  class Window_MyWindow extends Window_Base {
      refresh() {
          this.drawText("This is a test message", 0, 0, this.contentsWidth(), this.lineHeight());
      }
  }

These are basically equivalent. Thankfully the whole engine is written in the same way that classes work in ES6, so everything actually just works with the new syntax.

People also still use var instead of let and wrap their things in function that is called immediately instead of just creating a scope with {}, which would just as well hide all names if you use let instead of var.

Of course, these observations are made only from the forums and some rare GitHub code one can find. Perhaps the people behind big games, knowledgable in javascript, use all these features, but we'll never know that. Still, the bad old code suggestions given on forums are somewhat disappointing, I hardly found anything useful there, and had more success just reading the engine code instead.

The peculiarities of event processing and drawing

Now, event processing is quite interesting in this engine. You might want to know this, if you plan on using the events provided via the editor in a custom scene that does not inherir or use the Scene_Map utilities. Maps are scenes which draw tilesets, have events, and are basically where the gameplay is. But there are other types of scenes too. The other important one is Scene_MenuBase, which has some utilities for implementing menus. So, if you want to have a custom menu and have events in it, or show images in it with the built-in commands, you'll have to work a bit for it, because Scene_MenuBase doesn't process events or draw sprites!

After some digging through the code I have figured out several things about how eventing and sprites work, and that's where some interesting differences from other engines surface. Usually, you either have a global manager that draws things and a global manager that processes events, or the objects themselves draw things and process events. But rpg maker mv seems to use both at the same time: to process events, you have to first create a Game_Interpreter and save it somewhere, then ask a global manager $gameTemp to create a reservation for the common event you want to run, and only then ask the interpreter to actually get the event from $gameTemp. After that, just call its update function every frame to make it process whatever the common event does.

The code looks something like this:

  class Test_MenuBase extends Scene_MenuBase {
      start() {
          // Reserve a common event received as a parameter to the plugin
          $gameTemp.reserveCommonEvent(Number(params["testEvent"]))

          // Create an interpreter
          this._interpreter = new Game_Interpreter()
          // Actually get the reserved event into the interpreter and clear the reservation
          this._interpreter.setupReservedCommonEvent()
      }

      update() {
          // Update the interpreter every frame
          this._interpreter.update()
      }
  }

Now, it will run the events, but that's not all of it.. It won't just draw pictures for you! Pictures also use this strange combined approach to get drawn. So, if you want to draw pictures, you have to add a Spriteset_Base to your scene. Which has a very annoying built-in behaviour of drawing a black background, that you might want to remove. The Spriteset basically takes all requests for drawing images with the built-in draw image command and draws them. You can also draw them manually by adding a Sprite_Picture to your scene with a specified picture number, but Spriteset_Base does this for you. The Map scene has both the spriteset and game interpreter in it, so it will process events and draw pictures, but other scenes don't. So if you add them to your scene, they will be able to do it. Quite obvious. You can also ask another manager to draw a picture instead of doing it from the editor, since all editor commands go through these managers. For drawing pictures, the manager used is $gameScreen. For example, call $gameScreen.showPicture to do the equivalent of what the editor event "draw picture" does.

Here is an example of a scene that can both draw pictures and process events:

  class Spriteset_Menu extends Spriteset_Base {
      createBaseSprite() {
          // Call the base function to create all the sprites first
          super.createBaseSprite()

          // Remove the black screen background. There's really no use for it in menus,
          // since it obscures the background
          this._baseSprite.removeChild(this._blackScreen)
      }
  }

  class Test_MenuBase extends Scene_MenuBase {
      start() {
          // Call the base function to do whatever it does first
          super.start()

          // Create the sprite set and add it to the scene
          let spriteset = new Spriteset_Menu()
          this.addChild(spriteset)

          // Fetch the common event that will possibly draw pictures
          $gameTemp.reserveCommonEvent(Number(params["testEvent"]))

          // Create the interpreter and get the event into it
          this._interpreter = new Game_Interpreter()
          this._interpreter.setupReservedCommonEvent()
      }

      update() {
          var active = this.isActive()

          // If you want for timed things to work, like picture movement, you have to update the $gameTimer manager too
          $gameTimer.update(active)
          // Update the game screen manager every frame, so it draws things
          $gameScreen.update()

          // Updates the interpreter, so it works on the events
          this._interpreter.update()

          // Call to the parent class' update so it does whatever it is supposed to do too
          super.update()
      }
  }

That's about it

That's about all I have managed to learn recently, for the particular task that I may be doing in the near future. I'll probably have to dig some more into other systems later, like the combat system. But I haven't done that yet. I imagine all the peculiarities apply to other systems as well, if they were designed by the same people.

I've hardly been doing anything recently, so I thought I might as well write out my thoughts on whatever it is I have figured out with RPG Maker MV, and hopefully this may help someone in the future.

Thank you for reading my blog post :)

Game thing progress #9, more editor things

I'm not dead, yet. The past few months have been rather boring in terms of things made, since I had to work on my diploma a lot. Hopefully I'm done with that soon and can come back to doing things I actually like. I'm actually using this game as my diploma project without any modification, so that's something.

I was told my game wasn't that impressive, that's true, of course, though the game is not the focus of the diploma, the engine is. So, I made an arkanoid clone in one evening just to make a completely different thing. To make it I had to extend the modding API slightly, but now the walking mode pretty much is all moddable too, so you can basically make your own new game using it, if you for some reason wish to do it. The documentation is basically non-existant on it, but you can look at the code in resources/mods/example and go from there, probably. Maybe I'll add some comments there to explain everything that is happening in the future.

Some fun editor things were implemented, like adding and selecting entitites that don't have a collider. Some more were added, since I wanted to make at least one room completely or at least mostly in editor. Which I did, but only one for now. Hopefully more to come soon.

Here's how the editor looks now, fancy buttons:

nil

The asset tab allows to add assets with the UI, too. It even has a fancy file selection window:

nil

When the asset that is in use is edited, the system tries its best to find and replaced all the usages of the old asset with a new one. Plus, if a Drawable component is added to an object, it initially has a placeholder black-and-pink texture which cannot be saved and serves as a temporary value until the actual texture is selected.

Other than that, the callback system has been adjusted to allow including type requirements for callbacks, so the editor UI can actually check these requirements and draw the appropriate editor. Basically, after you create a callback you call a special function and pass the type data into it, and it saves it in a special place for later usage. Here is an example of how it looks in code:

debug_components.declare_callback_args(
   M.interaction_callbacks.look,
   { prefab = "string" }
)

The callback accepts a single string argument in a map, the argument name is prefab. The UI uses that to create an editor that shows the appropriate table. The types can even be nested if some argument is a table in the aforementioned declaration. Or it can be a freeform table if its type is declared as table.

Most recently, I've tried to replace the SFML audio module with SDLmixer, which also made me add the entire SDL (though I've tried my best to disable unneeded things). The reason being that SDLmixer can have sound libraries linked statically into it and I can select only those I want to have - namely OGG. All the sounds are in OGG anyway but SFML also requires FLAC, for example. And it links to everythng dynamically which is a pain. I've been doing the SDL thing in a separate branch for now, hopefully I will merge it into master soon and the next release on will only require you to have alsa/pulse on linux and nothing additional on other operating systems.

Did you know that building SDL is actually a huge pain in the ass? Their CMake file sucks and for some reason SDLmixer's one has a check around everything that makes it only do something when building on android. I think I somewhat figured it out, but you can never know with these things.

Almost forgot.. I fixed an annoying bug I had with the TOML component saving. In TOML procesing code, the entity table itself is referred to as "self". So, the code tried to get the "self" node on every entity, even if one did not exist (such a node would have a path like "entities.entity name", with no component). If such a node does not exist in a file, but its source is retreived from code, it will point to some other node that actually exists which DOES NOT WORK and breaks things. So, now it only tries to use the "self" node in case there are no other nodes but the entity exists in the file: therefore it is guaranteed that the node will be pointing to an entity node with no components. Because of this bug, the saving was inconsistent: either the entity or the first component were selected at random, and when entity was selected things broke.

The shaders have been changed a bit, mostly moved to storing them in lua and C++ just sets them and then gets them from lua. With that, they can be edited more conveniently in the editor thing (which is basically the same as the callback or other table one, with types defined in C++ code and stored in lua).

That's about it, I think. Not much, but it's nice to write these things down sometimes. Hopefully someone actually reads them. And as usual, thank you for reading my blog post!

Game thing progress #8, actually mostly about editor stuff

Hello, Hello, all two (three?) of you reading. It's good to see you again. Once again it has been some time since the last post.

Many things have happened, mostly me also helping out on some other game, which also takes time (actually, I will get paid for it when I sort out paypal stuff so I'm not just wasting time, hopefully). But really, who cares about that, right?

You're probably here to read the progress on THE game, not some other game. It's been pretty slow. The current part will have more walking-mode content than all the previous ones together, and drawing and programming that stuff takes a lot of time, although I haven't touched it in a.. while. Mostly have been procrastinating or doing something else, after drawing three rooms and implementing two.

Since the release, I've implemented modding for the terminal-mode of the game. Mods can basically do everything normal lines can, but are loaded from the instance menu (you'll have to play the game if you want to know where the menu is). I've written an elaborate instruction on how to make them here, although this will only be relevant whenever the next release comes out. Nevertheless, I think it came out pretty well. When mods are loaded, they are provided a separate line environment than can only access its own lines and can't touch the main-story lines or other mods' lines. Mods can also load scripts, these are not vetted like the lines are, as I couldn't figure out a good way to do so. However, they're always available in namespace mod.<script name here>, that mod is literal, so you don't have to know the name of the mod. In general, the name of the mod never needs to be used in the API, so it's only for the players. When organized as such, mods can't interfere with each other.

For terminal mode, more smooth scrolling was implemented, which, unlike previously, actually looks pretty good and is better on the eyes than the text just jumping. Here's how it looks:

Some other improvements have been have been made to the room loading stuff, such as making passages fallback to previous days room files if one wasn't find in the current day, so rooms don't need to be repeated if they don't change. As part of work on the next day's walking part, touch-activated interactables were added, both always-working and one-time working (based on the activatable callback). These are used for main character commentary on some things, for example, and room transitions in some places.

A fade-in/out has been implemented and used whenever logically needed, like in transitioning from terminal to walking and transitions between rooms. It looks pretty good, and makes the player unable to walk in walking-mode while transitioning.

A way for coroutines to wait on something has been added, by making coroutines return special values from yield (in a way, this is similiar to how Unity Engine does it). This also has been used for providing coroutines with delta time. Previously it was wrongly passed as an argument, now when the coroutine resumes yield returns delta time for it.

A generic look-closer-at-thing system has been implemented, as there are now several things to look at that only show picture and text.

And now.. for the actually intersting part: editing TOML assets while in-game. For this, the pretty bad lua TOML parser has been replaced with a better C++ one and passed to lua. Additionally, all information on the position of the TOML node is saved, in C++ the whole parsed TOML file is saved for later, and for lua only the file and the path to the node is passed. When a component wants to have things saved, it provides a file and a path to the node and the toml-node-in-file is looked up and replaced.

A read-only editors are implemented for Transformable and Name, and for Collider an editor that actually does things is implemented (it also updates transformable in TOML source when needed).

As of now, new components can't be added, and neither can new entities, but the existing components can be edited. This includes checks for defaults, which are not written to the file if they are not overriden in the editor. Otherwise, if the default value is changed the key-value pair will be added to the TOML code.

The serialization-back system itself is implemented by finding the relevant place in the TOML file and replacing just this place with manual string manipulation on the C++ side. This is done so as to save the formatting and such of the original file, as it seems that no TOML libraries are able to do so and always re-format and re-arrange the file (very rude of them). As such, a system to only modify the data in relevant parts was made.

As for prefabs, currently editing anything using non-overriden prefab value will modify the prefab itself. This will probably have to be changed in the future somehow.

The editing will hopefully be expanded in the future and help with making new rooms, as it becomes quite tideous to maintain by hand. The hardest parts may be adding new entities and components, in particular figuring out where to put them in the file. Hopefully, I'll be able to work on that.

Here's how all of that looks:

Shown is the Collider editor. Currently editor clicks are only recognized for objects with colliders, other objects will probably have to somehow be made available otherwise as there isn't really an easy way of finding them in the world, although I do have some ideas for the future. Otherwise, objects with colliders can be dragged with mouse with CTRL+Click and clicking on an object selects it for editing, while double-clicking anywhere where there is no object deselects it.

Also, after my friend played the game (someone actually played it, crazy, huh?), he found out that it may so happen that non-english layout broke the game sometimes. That is because lua has string.char and utf8.char and the first one can't handle anything that is not ASCII. So I've replaced all mentions of string.char with utf8.char to hopefully fix the problem. That same friend found some typos and suggested changing the "description" color in the terminal part, as it didn't look well on black background and was hard-ish to read. So now the color is a bit more soft, as you may have noticed in the first video in the post. Another thing he noticed is an inconsistency where you didn't see something but it was mentioned later, that was fixed too, with the new text not mentioning the thing if you haven't seen it.

That was quite a lot of text now, wasn't it? Two videos, too! That's a record. I'm going back to making the editors better for now, probably. This seems to be promising. And also helping with that other game I mentioned. Happy new year, and thank you for reading my blog post!

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:

1:
  custom:
    class: { module: "terminal.select_line", class: "SelectLine" }
    data:
    - 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 :)

Game thing progress #6, the first public release, automatic builds, and other things

Here I am again, with another post. Since the last time, the game actually saw its first public release on itch.io, as well as its source code and assets have been made public on github under the GNU GPL 3 license for code and the CC-BY-NC-SA 4 license for assets. Go check them out if you want, the code has quite a few intersesting places. And of course, you can now actually play the game for yourself :)

The whole story from the original .org file is now in the game and playable, which includes the first two days. I'll probably be working on expanding the story further soon.

Now, for the actual changes that happened since the last post.. When testing on Mac OS, I was told that the game actually didn't work, because the libraries it needed aren't usually there on user systems. So I had to learn how to make bundles for Mac OS. Luckily, CMake has a few nifty things to help with that, namely the fixup_bundle function from BundleUtilities which automatically finds the frameworks needed for the game and copies them into the bundle, together with the game binary. It's used like this:

install(CODE "
include(BundleUtilities)
fixup_bundle(\"${CMAKE_BINARY_DIR}/someone.app\" \"\" \"\")
" COMPONENT Runtime)

This means that when running make install, CMake will fix the bundle for me. Apparently, it has to be done on the installation step for some reason, which caused quite a bit of trouble because when you use add_subdirectory, the install target also installs all the things from those subdirectories. And nobody says how to fix that! I found an answer on some old CMake mailing list.. apparently if you add EXCLUDE_FROM_ALL as the last argument to add_subdirectory then it won't try installing things from subdirectories! So I added that to all the libraries that tried doing so.

Also in the process of building for MacOS, a friend of mine, who was basically the one who made it work on MacOS initially, discovered that lua from the lua github repository isn't actually meant for other people, but for lua developers, because it's missing a lot of things that are in the normal release tarball that is on the lua website. So, he replaced the lua submodule with a call to ExternalProject_Add that would download and build lua from that tarball. That made lua a lot easier to build on all systems, as there are now no hacks like compiling lua with gcc manually, it all "just works" if the correct platform is passed to the lua makefile.

Another small change that had to be made for the game to work with MacOS bundles was making it change the current directory to the one the binary is in, so it can find the resources directory. This means that the game can now be launched from anywhere, which is a good change for all systems, but crucial on MacOS because bundles run in a directory where the bundle is, not in the directory where the binary is.

Another interesting thing that happened is that I finally figured out why the game was segfaulting when closing, but only in release mode. The C++ static class members were to blame, and SFML in part. Apparently, SFML fonts implicitly depend on an OpenGL context, which, by the time the static destructors are run, is long gone! So making the static class members not static and passing them explicitly where needed fixed the segfaulting.

Another small quality of life change to the dialogue system format has been made: the answers of the player previously had to always specify the next line, even if it was a numbered line that was easy to figure out, which now it does.

Previously, the help text that said things like "Press 1 to continue" was shown inside the terminal with the same color as the character speaking, now this text is outside the terminal. It is also used in an all-new line type: text input line. This line has some "before" and "after" text, and between those the player can input some arbitary text with the keyboard (and the help line says they can do so)! For now, this is used to allow the player to input their name, and other characters will refer to them by that name. The name is saved in the same place all other variables are, and is inserted into text when the text is created by using Lua's string.gsub to replace things like <p> with the actual value of the variable p (which is the variable used for the player name throughout all of the story, but also it's the default name if the name input is skipped).

And now.. for some pictures! A debug menu has been added to simplify testing (for now, only for the terminal mode), the debug menu uses Dear ImGui and the imgui-sfml library to make it work with SFML easily.

Here is how line switching looks: you input the whole name and it switches the game to that line (very simple and very useful!):

And here's how the variable menu looks, allowing to see variable values (and even toggle boolean values, though this is an old screenshot where this isn't yet implemented):

nil

This menu is toggled by the tilde key, I left it in releases too, just in case.

The shaders for the walking part have been changed a bit, so now there's one shader with the computer screen light and one without. It's not the best solution probably, but it works for now.

The environment images have been disabled for the release because there aren't enough of them to cover everything yet, I'll bring them back when I have some more, but for now they're copied to the release but now shown

A lot of optimization work has also been done before release, the terminal part now works in more-or-less constant amount of memory, reusing as much as possible (not creating new text objects and recalculating them every frame is the biggest optimization probably). Many calculations that are used a lot have been cached, for example the size of the terminal frame is only recalculated when the window size changes, so it might even only get calculated once and then just be reused all the time.

Now a little bit about build automation: itch.io has a very usful tool called butler, which allows publishing on itch.io automatically and easily. I just download and unpack the archive on the autobuild machine, do ./butler push <release_dir> vaartis/someone:<channel> --userversion <version> and it uploads the difference between builds and makes them available under the new version, also hiding the old one. This works surprisingly well and I had basically no problems automating and using it, so all release builds (tagged as releases on github) are now also automatically published on itch.io. Since the initial release, I've made two bug fixing releases which were automatically pushed to itch using butler. Big props to people at itch.io for making such an easy to use tool.

And.. I guess that's all for now, even though the game isn't popular or anything judging from the itch.io statistics, that's really to be expected. I'll continue working and improving it. Thank you for reading my blog post!