🌱C3 is C with the rough edges filed off - modules, slices, and defer, while staying close enough that the null0 header maps over almost unchanged.
- Template: cart_c3 - press "Use this template" and you have a working game.
- Docker image:
ghcr.io/notnullgames/null0-cart-c3:latest(linux/amd64 only - runs emulated on Apple Silicon) - Your code:
cart/main.c3, compiled with c3c - Bindings:
carts/c3/null0.c3(baked into the docker image for you) - WASI is available, so ordinary file and stdio calls work.
- See carts made with C3
- API docs for C3
building
You do not install c3c - the docker image has it, and the current null0 bindings, baked in. There is nothing in your project to keep in sync with the engine.
docker run --rm --user $(id -u):$(id -g) --platform linux/amd64 \
-v ./cart:/src -v ./webroot:/out \
ghcr.io/notnullgames/null0-cart-c3:latest mygameThe template wraps that in npm start, which also serves the result and rebuilds when you save.
C3 notes
module mainplusimport null0.
a cart, in C3
This is carts/c3/simple/main.c3 in the engine repo - the same file CI builds into the cart below, so it always compiles.
module main;
import null0;
fn void load() @export("load") {
null0::clear(null0::BLUE);
null0::draw_circle(100, 100, 50, null0::RED);
null0::draw_text(null0::FONT_DEFAULT, "hello from C3", 170, 92, null0::WHITE);
}
// callbacks (optional - implement as needed)
//
// fn void update() @export("update") {}
carts/c3/simple/main.c3callbacks
A cart implements the callbacks it cares about. In C3 they look like this:
fn void load() @export("load") {}See anatomy of a cart for the full list and what each one is passed.