raylib examples in Clojure

78 raylib examples on the JVM, calling the C library directly through coffi over JDK 22+'s Foreign Function & Memory API. No JNI, no wrapper library, no codegen — defcfn binds a C function and you call it.

A few of them

core 23 · models 21 · shapes 15 · games 9 · audio 4 · text 3 · textures 2 · shaders 1 — every one of them, with a preview.

Why this is interesting

Calling C from the JVM used to mean JNI: a C shim, a build step, and a native library you had to ship yourself. Project Panama removed the shim. coffi puts a Clojure face on it, and what's left is small enough to read in one sitting — which is what makes this a decent place to learn the FFI rather than just a pile of games.

How it fits together

flowchart LR
  subgraph ex["78 example namespaces"]
    e["asteroids · tetris · lorenz-attractor
basic-lighting · solar-system · …"] end subgraph bind["src/raylib — the binding layer"] d["defcfn per C function,
split by raylib module"] s["structs.clj — defalias
layouts for Color, Vector2,
Rectangle, Camera3D, …"] end co["coffi"] pa["JDK 22+ Panama
Foreign Function & Memory API"] rl["libraylib 5.5.0
bundled under libs/"] e --> d d --> s d --> co co --> pa pa -->|"C ABI, no JNI shim"| rl

Adding an example touches exactly four places — the source namespace, a deps.edn alias, a bb.edn task, and a row in the bb/helpers.bb registry. Miss the registry row and the example still runs, but nothing lists it.

What's here

No JNI, no shim

Panama links raylib's C ABI directly. There is no C file in this repo and nothing to compile before you start.

Nothing to install

raylib 5.5.0 ships prebuilt for macOS, Linux and Windows under libs/, picked by OS and architecture at load time.

Live REPL into a running window

An embedded nREPL on port 7888 per example, so a draw function can be redefined without closing the game.

A linter that understands the FFI

A clj-kondo hook teaches it to see through defcfn, so a binding called with the wrong arity is caught statically instead of as a native crash.

Compile-checked headlessly

bb check requires all 104 namespaces without opening a window — the check that catches a broken example the one you ran wouldn't.

Every example recorded

All 78 carry an animated preview in the catalog, captured from the real running example rather than mocked up.

Quickstart

git clone git@github.com:burinc/b12n-raylib-clj.git
cd b12n-raylib-clj

bb info            # grouped cheat-sheet of every task
bb asteroids       # run one (opens a window)
bb examples        # all 78, grouped by category
bb check           # headless compile of every namespace

Needs JDK 22 or newer — that is where the Foreign Function & Memory API arrives, and there is no fallback on an older JVM. babashka gives every example a friendly task and is the only path that works on both macOS and Linux; without it, macOS can use clojure -M:<alias> directly. Released under the zlib license — the same one raylib itself uses.