less_retarded_wiki/licar.md
2025-06-26 21:52:18 +02:00

8.3 KiB

Licar

Licar (short for libre car), also known as the best racing game ever made, is a fully public domain, free software and free culture 3D racing game by drummyfish, highly inspired by the proprietary game Trackmania. Licar is made in similar fashion to Anarch (another drummyfish's game) but is a little more bloated: it is a fully 3D game made with small3dlib and tinyphysicsengine and although it's not the most minimalist game under the Sun, it is still very much KISS, extremely portable, not using any third party libraries etc. The git repo is currently at http://git.coom.tech/drummyfish/Licar; version 1.0 of the game was released on 25.06.2025 after 329 commits. The creation of Licar was conducted purely with free software (GIMP, Blender, GNU/Linux, vim, ...) and relatively old computers (mainly Thinkpad X200).

The game's features include a fully 3D, completely deterministic physics, lovely soulful software rendering, replays, ghost cars and custom maps (written in a plain ASCII text format). In the base package there are 5 standard, 5 tiny and 2 bonus maps.

Drummyfish made Licar to fulfill one of his long held dreams of making a Trackmania clone, for he used to love the game but had to abandon it once he started abstaining from proprietary software. The project also offered an opportunity to showcase drummyfish's major libraries and to demonstrate some of the LRS principles on a bigger project -- although the game isn't truly an LRS ideal, it still shows how powerful minimalism can be, even when applied to a relatively mainstream vision of what a video game is. By this it can potentially and hopefully reach more normies.

Just like Anarch, Licar adheres to basic LRS programming practices, for example it is fully written in C99, is completely public domain under CC0, uses no build system, no third party libraries, doesn't rely on standard library, doesn't use floating point and embeds its configuration and assets right in the source code (except for optional music and external data file). The whole game was made completely from scratch, including all assets, the text font, recording own musical samples for custom sound font for the soundtrack etc. The whole code has around 25 thousand lines of code. Needless to say the game is very portable end efficient as a result: the compiled binary (including embedded assets) usually weights around 300 kB, the program runs with less than 500 kB RAM on CPUs clocking even around 100 MHz. It was even run on Pokitto, albeit in an extremely limited way.

Technical Detail

Licar is wholly written in C99 and only uses small3dlib (S3L) and tinyphysicsengine (TPE) as libraries -- apart from these no other libraries are used (not even standard library, except for using fixed size integers from stdint.h). The code is a single compilation unit, i.e. everything is implemented as header files (including S3L and TPE) that are included by a frontend which is then the only file to compile (no need for manual linking, build systems and whatnot). Of course specific frontends have to use some kind of I/O library to deliver interaction with the player, but these are not hard dependencies of the game itself, only of a specific frontend -- several frontends are implemented, including SDL2, CSFML and X11. Frontends are very simple as they're only required to implement extremely basic functions such as a pixel drawing function, key press checking function and a few others. The game was successfully compiled and played under GNU/Linux, Win$hit, OpenBSD, on Raspberry Pi, in web browser and even on very weak devices such as Pokitto and ESPBoy, albeit in a very limited "tech demo" way. When counting raw lines (wc -l), all code (including frontends etc.) totals around 25000 lines of code, whilst only the pure game code (only header files) has around 21000 lines.

No floating point is ever used in the source code, everything (including 3D rendering and 3D physics) is implemented with 32 bit fixed point.

Graphics: like with Anarch, rendering to actual screen is realized through a frontend-defined pixel drawing function that's used by the game code to render everything from GUI and text to the 3D view. RGB565 (65536 colors) is used as a color format, with the option to turn on RGB332 (256 colors) as well. All images are embedded in the source code and stored in 64x64 resolution in indexed format (except for sky images which are effectively composed of 2x2 normal images to give a higher resolution). The car 3D model is also embedded in source code. The models of map blocks are created in code. When loading a map, its 3D model is created and invisible triangles are culled away (which is a little time consuming and makes bigger maps take longer to load). The map model triangles are then sorted so that the map is split into 64 (4x4x4) chunks -- only nearest 8 chunks of the map are being rendered at any time. Far away chunks are cheaply drawn as a very primitive "LOD", simply a flat-colored 2D half-transparent square. All transparency is handled by dithering. Text is drawn using a custom simple, vector, "segmented-display-like" font whose data are embedded in the source code.

Physics: physics is deterministic and is always calculated at 30 ticks per second, no matter what the rendering FPS is, interpolation is additionally applied to smooth the animation for rendering. Internally the car is composed of 5 spheres (4 wheels and the body) and is technically a soft body, but the shape is iteratively "stiffened" so that it appears as a rigid body. The relative position of the spheres is used to determine the car's orientation which is then applied to the 3D model for rendering. The map's shape in the physics world is modeled by a sort of signed distance function to handle collisions with the car.

Audio: all audio is in very simple 8 bit 8 KHz mono format. Sound effects are all generated procedurally. The game comes with a manually created background music track stored in raw format in a separate file, which can be played by the frontend if it can and wants to.

And finally some more uncategorized details. Maps are created in a plain text mini-language that specified where to place individual map blocks, what material and transformation they have etc. The process of loading a map includes reading this format and transforming it into the internal binary representation in which blocks are sorted so that looking up blocks can be done very quickly with binary search (this is crucial for resolving collisions as we need to quickly check the car's nearest blocks for collisions). Replays are similarly stored in a plain text format -- each replay record takes 16 bits and stores a change in input along with ticks since the last record (if the bits don't suffice to encode the ticks, a redundant no-change record is simply inserted). All these text data (i.e. mainly maps and replays) are stored in a virtual data file -- behind the scenes this files consists of the internal data file (one containing the basic maps, compiled right in the binary) and an optional external data file, which on platforms with filesystems is a normal file that can be edited to add more maps etc. Almost everything in the game is optional and can be turned off so that it's possible to play it on any kind of potato -- there can be no sound, texturing, no file system, no color display etc.

Postmortem

TODO: some reflections n shit here

See Also