dotframe
v0.2.0
Published
TS-first game engine and agent-first CLI: one codebase for web, Discord, iOS and native binaries
Maintainers
Readme
dotframe
TS-first game engine. One TypeScript codebase runs on the web (WebGPU) and compiles to native macOS and Windows binaries with scriptc, with no JavaScript engine in the binary.
Status: S5 in progress (porting Crafter Smash). examples/canvas2d exercises src/draw2d.ts, an immediate-mode 2D layer modeled on Canvas2D (transforms, alpha, concave paths, arcs, strokes, PNG sprites) so Canvas2D games port mechanically. Before that, S4: examples/smash-lite is a two-player platform fighter: keyboard and gamepad input, fixed-step AABB physics, hitstun, knockback that scales with damage, and KOs. DF_DEMO=1 (native) or ?demo (web) lets scripted players fight, which is how CI captures it. Earlier slices: examples/suzanne loads a glTF mesh, spawns three entities in a minimal ECS and renders them lit with depth and a perspective camera. The same game code renders in the browser (WebGPU) and in native macOS and Windows binaries (SDL3 + wgpu-native through a flat C shim). CI runs both binaries and captures them with cuse.
CLI
dotframe is an agent-first CLI over the engine. The simulation is deterministic, so an agent can play a game without a screen, render a frame with the real renderer, and catch netplay desyncs before a real match.
npm i -g dotframe # needs Bun on PATH
npx skills add crafter-games/dotframe # installs the agent skill stub
dotframe new my-game --template fighter # fighter, platformer, blank
dotframe sim --mash 7 --frames 600 --json # headless run: state + checksum
dotframe snap --frame 300 --mash 7 # one frame through WebGPU (agent-browser)
dotframe replay record replays/a.json --mash 7 && dotframe replay verify replays/*.json
dotframe desync --latency 120ms --jitter 30ms
dotframe build web|ios|macos|discord
dotframe deploy web --prod --dry-run # external actions need --yes
dotframe doctor --fix
dotframe skills list # guides bundled with this versionA game opts in with a dotframe.json (targets, deploy, relay, vendor links, local-only assets) and a sim module that default-exports defineSim from src/sim.ts. Agents start with dotframe skills get core. Every command takes --json; errors carry a code, a fix, and the skill to read.
cli/: the CLI (Bun).skill-data/: the guides served bydotframe skills.skills/dotframe: the discovery stub thatnpx skills add crafter-games/dotframeinstalls.templates/: thedotframe newtemplates.
Layout
native/df_native.c: flat C ABI over SDL3 and wgpu-native. scriptc FFI accepts scalars and byte spans only, so the shim owns every WebGPU struct.src/gpu.ts: backend-agnostic types for game code. Backends are plain objects of functions, because scriptc compiles structural types as record copies and a class cannot stand in for an interface.src/math.ts,src/ecs.ts,src/gltf.ts,src/render.ts: column-major matrices, a Map-per-component ECS, a.glbreader (positions, normals, indices) and a lit mesh renderer.src/input.ts,src/physics.ts,src/shapes.ts: engine key ids mapped per backend (SDL scancodes,KeyboardEvent.code, first gamepad), side-view AABB physics, and a unit box mesh.src/draw2d.ts: Canvas2D-style layer batched into one vertex buffer, one draw per texture. Setters replace property assignment (setFillStyleforctx.fillStyle =). PNGs decode with stb_image natively andcreateImageBitmapon the web.src/audio.ts,native/df_audio.c: sound effects (MP3, volume, playback rate), square tones and one streamed music track. Native mixes in C over SDL3 audio with dr_mp3; the web uses Web Audio and an<audio>element.examples/audio-checkplays a known timeline that CI records with SDL's disk driver and verifies withtools/check-audio.ts(segments, 880 Hz tone, 262 Hz music, silence after stop).test/:bun testcovers color parsing, triangulation and physics (landing, walls, ceilings, falling off edges).src/native: FFI declarations and the native run loop.native/ffi.{macos,windows}.jsonbind them for every example.src/web: the browser run loop overnavigator.gpu.examples/*:game.tsis shared;main.native.tsandmain.web.tspick the backend.assets/audio/*.mp3: original test sounds generated with ffmpeg.assets/fonts/*: Bangers and Archivo Black (SIL OFL, seetools/fonts/) baked into SDF atlases bytools/bake-font.c.assets/crafter.png: original 16x16 two-frame sprite, generated bytools/make-sprite.ts.assets/suzanne.glb: Blender's Suzanne from the Khronos glTF sample assets (CC0, Norbert Nopper / UX3D), packed geometry-only.scripts/build-native.sh: builds an example formacosorwindows.
Vendored dependencies (not committed)
- wgpu-native
v29.0.1.1prebuilt (wgpu-macos-aarch64-release,wgpu-windows-x86_64-gnu-release) invendor/wgpu/{macos,windows}. - SDL3
3.4.16source invendor/SDL3-3.4.16, built static intovendor/build/sdl-{macos,windows}. Windows is cross-built with zig viavendor/toolchain/zig-windows.cmake.
Build
scripts/build-native.sh macos triangle
scripts/build-native.sh windows triangle # needs zig and @scriptc/runtime-win32-x64-msvc
scripts/build-web.sh triangle # then serve build/web/triangle