A first-person wave-survival shooter built from scratch in Odin with raylib, rendered with a classic Wolfenstein/Doom-style raycasting engine. Fight off waves of dogs, terrorists and armoured juggernauts across randomly chosen arenas, unlock heavier weapons as your score climbs, and chase the high score.
- Raycasting engine — DDA wall casting, textured floor and ceiling, and vertical mouse-look via horizon shearing. Everything (walls, sprites, weapons, sounds) is generated procedurally in code, except the sound files.
- Depth-sorted billboards — enemies, barrels and pickups are drawn as sprites with correct wall and fence occlusion.
- Waves — enemies spawn in escalating waves with scaling health and damage.
- Dogs — small, fast, melee (and they bark when they get close).
- Terrorists — shoot from range when they have line of sight.
- Juggernauts — slow, heavily armoured, hit hard, drop a med-kit on death.
- Weapon progression — start with a pistol, unlock the shotgun and machine gun as your score climbs, each with its own view-model, fire rate and sound.
- Ammo economy — every weapon has its own reserve; enemies refund the ammo you spent hitting them (plus a small bonus), so accuracy pays off.
- Cover — solid walls block bullets; waist-high wooden fences are cover you can see and shoot over.
- Movement — strafing, jump and crouch (with view bob and a weapon view-model that sways and recoils).
- Random levels — one of four hand-designed 24×24 arenas is chosen each run.
- Menus & progression — name entry, pause menu, sound toggle, a persistent high score, and an end-of-run stats screen (score, wave, kills, accuracy, time).
Main menu — enter your name, then jump in:
| Corridor | Juggernaut & ammo drops |
|---|---|
![]() |
![]() |
| Pause menu | Game over stats |
|---|---|
![]() |
![]() |
| Action | Key / input |
|---|---|
| Move | W A S D |
| Look | Mouse |
| Fire | Left mouse button |
| Switch weapon | 1 2 3 |
| Jump | Space |
| Crouch | Left Ctrl / C |
| Pause | Esc |
| Debug top-down map | Tab |
In the main menu, type your name, then press Enter (or click Play).
You only need the Odin compiler — it ships with the raylib bindings and library, so there are no extra dependencies.
make runThe Makefile wraps the common tasks:
| Command | What it does |
|---|---|
make |
Show the list of targets (same as make help) |
make run |
Build and run the game |
make build |
Build a debug binary into bin/ |
make release |
Build an optimized release binary into bin/ |
make check |
Type-check the code without building |
make vet |
Run the Odin vetter |
make clean |
Remove build artifacts |
Or build directly with odin run src.
Sound is optional: drop audio files into assets/sounds/ (see
assets/sounds/README.md for the expected names and
free CC0 sources). Missing files simply play nothing.
src/
geo/ vector math
world/ game logic — map, raycaster, player, enemies, weapons, pickups
render/ drawing — walls, floor/ceiling, billboards, HUD, procedural textures, audio
game/ state machine — menu, gameplay, pause, game over, high score
main.odin
The dependency flow is one-way: render and game depend on world, and
world never depends on render, keeping game logic free of rendering
concerns.





