⚡Cyber is a fast, small scripting language. The VM is re-entered for each callback, so your top-level state persists between frames.
- Template: cart_cyber - press "Use this template" and you have a working game.
- Docker image:
ghcr.io/notnullgames/null0-cart-cyber:latest - Your code:
cart/main.cy, interpreted by cyber, baked into main.wasm - Bindings:
carts/cyber/null0.cy(editor definitions - the runtime provides the API itself) - WASI is available, so ordinary file and stdio calls work.
- See carts made with Cyber
- API docs for Cyber
building
You do not install cyber, baked into main.wasm - 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) \
-v ./cart:/src -v ./webroot:/out \
ghcr.io/notnullgames/null0-cart-cyber:latest mygameThe template wraps that in npm start, which also serves the result and rebuilds when you save.
Cyber notes
use null0, thennull0.clear(null0.BLUE).- The VM is re-entered per callback via
persist_main, so top-level state persists across frames.
a cart, in Cyber
This is carts/cyber/simple/main.cy in the engine repo - the same file CI builds into the cart below, so it always compiles.
use null0
fn load():
null0.clear(null0.BLUE)
null0.draw_circle(100, 100, 50, null0.RED)
null0.draw_text(null0.FONT_DEFAULT, 'hello from Cyber', 170, 92, null0.WHITE)
-- callbacks (optional - implement as needed)
--
-- fn update():
-- pass
carts/cyber/simple/main.cycallbacks
A cart implements the callbacks it cares about. In Cyber they look like this:
func update():See anatomy of a cart for the full list and what each one is passed.