Chapter 1: Yo, Odin: setup and a first look
This chapter: install and verify the Odin toolchain, set up your editor, compile and run a first program, and see the road ahead.
1.1 What we're building
Destroids, an Asteroids clone. You fly a vector ship in a wrap-around field of drifting rocks; shoot them and they split into smaller, faster pieces; clear the wave for a bigger one; you get three lives and a risky hyperspace jump. The finished game has:
- a twinkling starfield of ~380 points;
- a ship with thrust, inertia, and a flickering flame;
- rotating polygon asteroids that bounce off each other;
- sparks, spinning debris, shockwave rings, and screen shake on every hit;
- a HUD (score, wave, lives), plus intro, pause, and game-over screens;
- live-synthesised sound, no audio files;
- a high score saved across reloads.
All of it is canvas lines and rectangles, one WebAssembly module, three static files. No engine, no assets, no dependencies.
Why the constraints? When you can't reach for a sprite sheet or a physics library, you have to understand what a sprite and a collision actually are, and that understanding transfers to whatever you build next.
1.2 Why Odin, why WebAssembly
Odin is a compiled, statically typed, manually memory-managed language in the C tradition, by Ginger Bill. Four things make it a good fit here:
- It targets WebAssembly directly:
odin build -target:js_wasm32, no plumbing. - Array programming is built in: a
[2]f32behaves like a vector (add, scale, swizzle), which is exactly what 2D maths wants. - No hidden garbage collector: allocation is explicit, which matters in a 60 fps loop.
- It's small: you can learn the parts we need in one chapter.
WebAssembly runs compiled code at near-native speed inside a web page, reachable by anyone with a browser and no install step. Odin + WASM + Canvas is a dependency-free game target.
1.3 What you need
A desktop (macOS, Linux, or Windows), a terminal, a text editor, and a recent desktop browser. Destroids is keyboard-controlled, so it's a desktop game.
1.4 Installing Odin
Follow the official, always-current guide:
Odin builds on LLVM, so its one dependency is a matching LLVM/Clang, which that page pins per platform. In short:
- macOS:
brew install odin(Homebrew), or build from source against Homebrew's LLVM. - Linux: install the specified LLVM, clone Odin, run
build_odin.sh. - Windows: install the Visual Studio Build Tools, then use a prebuilt release or build from source.
Verify:
odin version # prints e.g. "odin version dev-2026-07"
odin report # diagnostics, paste this when asking for help
Odin note. Odin moves quickly and most people track a recent build. I use only long-stable parts of the language here, so any current Odin compiles it; Appendix D notes the few places most likely to drift.
1.5 Editor setup
Any editor works, but syntax highlighting and a language server, **ols**, give you autocomplete, and inline errors. The ols README has per-editor setup (VS Code, Neovim, Emacs, Sublime, anything with an LSP client).
The command you'll run most needs no editor:
odin check <directory> # type-check only, no binary: "did I just break something?"
1.6 Hello, Odin
// hello/main.odin
package main
import "core:fmt"
main :: proc() {
fmt.println("Yo, Odin!")
}
Run it from the folder containing hello:
odin run hello
# => Yo, Odin!
The essentials, unpacked properly in Chapter 2:
package main: a directory is a package; an executable's package ismain.import "core:fmt":core:is the bundled standard library;fmtprints.main :: proc() { โฆ }: Odin declares withname :: value; here the value is a procedure.fmt.println(โฆ): callprintlnfromfmt.
Odin note. Three verbs:
odin run(build + run),odin build(build only), andodin check(type-check only). You'll use all three.
That was a native binary for your machine. Soon we'll compile other code to WebAssembly: same compiler, different -target, and by the end you'll routinely build two targets from one project: the game to WASM, and the server that serves it to native.
1.7 The road ahead
Twelve chapters, each ending somewhere runnable:
- Setup and a first look (here)
- Enough Odin to be dangerous
- Odin meets the browser (WebAssembly)
- Serving the game (an Odin web server)
- The renderer, part 1: command buffer + bridge
- The renderer, part 2: canvas, loop, input
- The game takes shape: loop, state, ship
- Rocks and bullets: asteroids, shooting, collisions
- Juice: particles, debris, shake, starfield, hyperspace
- HUD, state, and a persistent high score
- A voice: synthesised sound
- Determinism, build, and ship
Then appendices: Odin quick-reference, full source listings, extending the renderer, troubleshooting, links, and changelog.
The project's final shape (don't create it yet):
yo-odin/
โโโ batch/ renderer library (Ch. 5โ6)
โโโ web/batch.js its JavaScript glue
โโโ src/ the game (Ch. 7โ11)
โโโ server/ the Odin web server (Ch. 4)
โโโ index.html the host page
โโโ dist/ build output (three shipped files)
โโโ build.sh
โโโ run.sh
Checkpoint
odin version works, you know the three verbs, your editor understands Odin, and you've run your first program.
Exercises
- Add a second
fmt.printlnline and re-run. - Use
odin build helloinstead ofrun; find and run the binary. What differs? - Break the program (drop a brace) and read what
odin check hellosays.
Further reading
- Odin: https://odin-lang.org/ ยท Install: https://odin-lang.org/docs/install/
- Overview (next chapter draws on it): https://odin-lang.org/docs/overview/
- ols: https://github.com/DanielGavin/ols
- Karl Zylinski, Understanding the Odin Programming Language: https://odinbook.com/, for the whole language when you want more than my slice here.