A raycaster engine for spaces that don't behave. Built in C with raylib.
Raykośa renders column-cast 3D environments where the geometry is allowed to lie. Rooms can be larger inside than outside. Corridors can connect places that shouldn't be adjacent. Perspective inconsistencies at seams are part of the aesthetic, not something to be corrected. The goal is spaces that feel present — solid, lit, atmospheric — while quietly breaking Euclidean assumptions underneath.
Renderer
- Column-based raycaster with DDA ray-marching and a software framebuffer
- Trilinear texture filtering across 3 MIP levels (64×64 base textures)
- Relief system: per-cell floor/ceiling bumps, dips, and slopes (cardinal prisms)
- Pillar walls formed by infinite-altitude relief cells
- Distance fog with independent floor/wall falloff curves
- 640×360 render, upscaled to 1280×720 with nearest-neighbour filtering
- Minimap overlay
Lighting
- Baked lightmaps at 4× grid resolution (96×96 for a 24×24 map)
- Point lights with ray-traced line-of-sight (12 samples/unit)
- Sun lights illuminating sky-exposed cells
- Independent ambient values for floor and ceiling
Billboards
- Single-sided (camera-facing) and double-sided sprites
- Cross-shaped rendering (two perpendicular quads — vegetation, pillars)
- Multi-face directional sprites (up to 8 viewing angles)
- Sprite-sheet animation with configurable frame duration
- Per-billboard collision with configurable radius
Collision
- 8-point circular approximation for smooth wall-sliding
- Billboard collision blocking (distance-based, opt-in)
- Grid bounds checking
Input
- Keyboard + mouse with configurable sensitivity
- Gamepad: dual-stick + D-pad, deadzone handling
Tooling
- JSON map format with sparse relief encoding
- Browser-based map editor (
tools/map_editor.html) - Unit tests for collision and map subsystems
Requires raylib and a C99 compiler.
# macOS
brew install raylib
# Build with Make
make # build
make run # build and run
make test # build and run tests
make clean # remove build artifacts
# Or build with CMake
cmake -B build && cmake --build build| Input | Action |
|---|---|
| WASD / Arrows | Move |
| Mouse | Look (yaw + pitch) |
| Gamepad left stick / D-pad | Move |
| Gamepad right stick | Look |
| M | Toggle minimap |
| ESC | Quit |
src/
main.c — entry point, game loop
map.h/c — map data structures, JSON load/save, compile
player.h/c — player state, movement, input handling
collision.h/c — 8-point circular collision + billboard blocking
renderer.h/c — column raycaster, billboards, lightmap sampling, minimap
config.h — all tunable constants (resolution, grid, input, physics, rendering)
jparse.h — single-header JSON parser with error reporting
tests/
test_main.c — test runner
test_collision.c — collision detection tests
test_map.c — map query, JSON round-trip, and edge-case tests
assets/
textures/ — 64x64 BMP wall/floor/item textures
maps/ — JSON map files
tools/
map_editor.html — browser-based map editor (JSON export/import)
docs/
Floor System Architecture.md — data model, compiled cells, and map format spec
Design Notes.md — intent and non-obvious decisions
See docs/Floor System Architecture.md for the full data model.
A Map holds two layers: facilities (the authored data) and compiled cells (what the renderer actually reads). Map_Compile() bridges the two.
Facilities:
- Plates — ground and ceiling base surfaces
- Relief — per-cell altitude and slope grids
- Lights — point and sun (up to 32)
- Billboards — sprites with collision, animation, and multi-face support (up to 64)
Compiled output:
MapCellgrid — per-cell geometry for the renderer- Baked lightmaps — floor and ceiling at 4× grid resolution
This split means the engine is indifferent to whether a map was hand-authored in JSON or spat out by a generator. Both look the same once compiled.
Multi-floor, multi-map, and portal rendering are planned.
SoizoKtantas