devlog1: initial commit 2
After some time away from game dev aspirations, I'm coming back with a good dose of motivation and purpose. My game "engine" exploration brewed for months and I've decided to skip this part and go to making a game directly.
This is a creative endeavor, I don't care about going fast. I will yak shave the tooling and quality as long as I have fun doing it.
February 2026
Setup
My $dayjob language, c#, is also used extensively for game dev and I can be productive right away with it. The language provides enough primitives to write performant code at the cost of tooling that kinda sucks outside of IDEs. As a bonus, there's a bunch of game making resources for c# online because of Unity, although it is almost only OOP focused.
I decided to to use MoonWorks as a light framework to build a data driven game without an engine. This is very close to where I was going with my engine exploration. It provides a thin c# api over SDL3 and low level stuff that almost all game need (video, images, file system storage). Also provides a game loop with enough hooks to customize it to your needs.
Complementary to MoonWorks, MoonTools.ECS is a lightweight ECS system. It less than 20 classes of straightforward c#. Easy enough to evolve if my needs grow outside the scope of this library.
Making the Factory
Since MoonWorks is not an engine, there's not much in the way of tooling around the core logic. In the same vein as my previous game dev work, I've built a starting dev environment around the project with mise.
As my first endeavor, I've built a lightweight build system named lbs. It is an evolution on the build system I made in bash scripts with mise tasks as the coordinator. Tasks are now in lua, as it will be the scripting and the modding language of this game and bash is just unfun to write. I got lucky on timing and could start using the new "file as complete program" feature of dotnet 10 to eject from lua into c# for the more complex task of parsing the sprite packer output.
#!/usr/bin/env lua
--[[
# [MISE] description="pack Sprites into atlas"
# [MISE] tools={lua="5.5.0"}
# [MISE] depends=["check-lfs"]
# [MISE] sources=["{{env.ASSETS_SPRITE_SOURCE_DIR}}/**/*.png"]
# [MISE] outputs={ auto = true }
--]]
local SPRITE_SOURCE_DIR = os.getenv("ASSETS_SPRITE_SOURCE_DIR") or nil
assert(SPRITE_SOURCE_DIR ~= nil, "ASSETS_SPRITE_SOURCE_DIR is nil")
local SPRITE_COMPIL_DIR = os.getenv("ASSETS_SPRITE_COMPIL_DIR") or nil
assert(SPRITE_COMPIL_DIR ~= nil, "ASSETS_SPRITE_COMPIL_DIR is nil")
local lfsplus = require("lfs-plus")
local sh = require("sh")
local tools = require("tools")
rm("-rf", SPRITE_COMPIL_DIR)
for entry, path in pairs(lfsplus.directories(SPRITE_SOURCE_DIR)) do
print("processing atlas: " .. path .. "/")
local source_target = SPRITE_SOURCE_DIR .. "/" .. entry
local compile_target = SPRITE_COMPIL_DIR
mkdir("-p", compile_target)
tools.cram(source_target, compile_target, entry)
end
example sprite packing task that combine many tasks building blocks: env loading, folder looping, and tool calling
Of course, automation is only as good as the ease to make it. So one of the first task I created is dev:new_task. The barrier of entry to automate repetitive operations should be almost none.
Graphics Pipeline
I can show images on the screen via a sprite batcher. I simply ported the SDL3 gpu pipeline I made in Odin.
a very inefficient nested loop is driving this tile floor
Next Steps
- mini homelab
- code hosting (forgejo)
- ci/cd (unknown, maybe dagger)
- file server for builds (copyparty)
- telemetry storage and dashboards (ClickStack)
- doc hosting (mkdocs)
- debug overlay (dear imgui)
- first gameplay element