This is quite an accomplishment.
Three-hundred-and-eighty-six days since the last post.
Gosh. Time flies.
Truth is that I’ve worked on #tofuengine for most of last year. In the previous devlog post I was presenting v0.10.0, and now I’ve just (finally) completed v0.12.0. Two full versions leap!
Contrary to what I earlier wrote, the API has been partially redone. Nothing too dramatic, but with some nice enhancements.
First of all, the build system has been enhanced by including GFLW’s sources straight into the engine code-base. This required some tricky changes to the
Makefile but simplifies the build process since, previously, at each new GLFW’s release I was required to separately build a static library for each supported platform… and that was painfully boring. But not anymore!
On the graphics side, the API has been partially redesigned. I wasn´t satisfied with the “intuitiveness” of the methods’ signatures, so I reorganized/reordered them to be more consistent. The
self instance is always the destination of a drawing operation and different types of drawing are performed with specific methods and not a generic
Canvas:draw(...) overloaded one.
Another aspect I wasn’t happy about was the input sub-system. Initially, #tofuengine only supported keyboard input leaving to the programmer the job to interpret and behave as needed. Gamepad and mouse input was later supported, but always with a single-player idea in mind (in fact, only a gamepad would work at a time and the keyboard could partially emulate it… and the mouse could be emulated with the gamepad… which was quite a mess). Since I wanted the engine to support at least two-player gaming (I always loved splits-screens :D), I simply added a new
Controller class encapsulating and abstracting the user input. Controllers can be enumerated and indexed, with the first two controllers emulated through the keyboard.1
At some point, I was intrigued by the idea of being able to write and ship a game/demo by only sharing its source code. Along with the code, also the resources would be somehow included in the… code. Well, for that purpose, a new
Storage class has been added that enables to (virtually) inject data programmatically into the file-system. The injected data is kept in a “cache memory”, like some sort of software RAM drive, overriding any other I/O primitive. When resources are injected at the start, they can be later accessed as ordinary (real) files. This also permits the hot-patching of any engine resource.
The most notable implementation introduced in the last two iterations, however, is the kernal. Evidently inspired, in its name, by Commodore PET’s it can be thought of as the bios/kickstart/kernal of the game engine. The core that makes it work.
Well, that’s not completely true. But sort of. Let’s make a step back.
Internally, the engine uses a mixture of plain-C code and Lua scripts for the implementation of the scripting API. An API class can freely have methods implemented in C or Lua. There are classes completely implemented with C code, while others are written in Lua code only. I got the inspiration for this from Wren’s foreign methods2, and the idea of writing a class’ code using the (more expressive) scripting language and delegating to the lower-level C code the implementation of faster and more-crucial logic (much like JNI and common to many other FFIs) was something I wanted to leverage.
In order for this to work Lua scripts were to be included in the game-engine code. Initially, I did this by hardcoding them into the engine executable itself. This was done automatically by the build process that luachecked them, converted to C code with
#include-ed into the module translation unit.
The same applied to generic assets that were included as resources. I’m referring to fonts, images, shaders, text files, and so on.
It worked, yep, but I didn’t like to code organization for this at all. Additionally, it was becoming more and more inconvenient to handle as the number of files to be embedded increased.
So I single-handedly redesigned that aspect and every resource have been moved to a packed archive (namely,
kernal.pak). The file needs to be present in the same folder as the engine executable and is mandatory for it to work properly.
Which is the benefit of that? Well, the sole fact the file is external permits a whole new degree of extension/customization/modding of the engine itself w/o the need of recompiling the engine executable.
Byte the way, namespaces have been flattened out and made more “standard”. For example,
require("tofu.graphics").Canvasis now accessed as
That’s pretty much all for this devlog.
In the next one, which I hope to write within the next two weeks, I will be exposing some major changes I’ve been considering and prototyping since last March.
Until then… see ya! :)