This project has been created as part of the 42 curriculum by lucpardo, pramos-c.
A raycaster inspired by Wolfenstein 3D, built on SDL3 through gfx/, a small window and drawing library.
cub3D renders a textured 3D view of a maze described by a .cub scene file.
The file declares the four wall textures, the floor and ceiling colors, and a
2D grid that defines the level layout and the player spawn. The player walks
through the level in first person using the keyboard and mouse, while the
engine casts one ray per screen column in real time to draw the textured
walls together with the ceiling and floor. The goal of the project is to
explore the fundamentals of raycasting, texture mapping, and real time
graphics programming in C.
Linux (tested on Ubuntu, Fedora, and NixOS), a C compiler, GNU make, the SDL3
development files, and pkg-config. The code is compiled as C2y (-std=c2y), so
use a recent GCC or Clang.
On Debian or Ubuntu:
sudo apt install libsdl3-dev pkg-configOn Fedora:
sudo dnf install SDL3-devel pkgconf-pkg-configOn NixOS, the dependencies are in shell.nix.
make # build cub3D
make clean # remove object files
make fclean # remove object files and the executable
make re # fclean followed by makeOn NixOS, run the build inside the shell:
nix-shell --run makeThe program expects exactly one argument, a path to a .cub scene file:
./cub3D maps/test.cubExample maps are available in maps/ (test.cub, corridor.cub, maze.cub,
pillars.cub, test_big.cub).
A .cub file contains two blocks. First the configuration identifiers, in any
order:
| Identifier | Meaning |
|---|---|
NO <path> |
North wall texture (.bmp) |
SO <path> |
South wall texture (.bmp) |
WE <path> |
West wall texture (.bmp) |
EA <path> |
East wall texture (.bmp) |
F R,G,B |
Floor color (each channel in 0 to 255) |
C R,G,B |
Ceiling color (each channel in 0 to 255) |
Then the 2D grid, where 1 is a wall, 0 is walkable floor, and one of
N, S, E, W marks the player spawn and initial facing direction. The
map must be fully closed by walls.
Example:
NO ./textures/north.bmp
SO ./textures/south.bmp
WE ./textures/west.bmp
EA ./textures/east.bmp
F 220,100,0
C 225,30,0
111111
100101
100001
1100N1
111111
The game also builds to WebAssembly with Emscripten. Both builds use the same game sources and the same SDL3 backend in gfx/.
On NixOS:
nix-shell -p emscripten python3 gnumake --run 'export EM_CACHE=$HOME/.cache/emscripten; make -C web wasm'
nix-shell -p python3 --run 'make -C web serve'Then open http://localhost:8000. The first build takes a few minutes because emcc builds its libraries into EM_CACHE.
Pick a map with ?map=<name>, e.g. http://localhost:8000/?map=maze. The default is pillars. Available maps are corridor, maze, pillars, test and test_big. Only lowercase letters and _ are accepted; anything else falls back to pillars. To add a map, drop a .cub file in maps/ and rebuild, since the folder is preloaded into the wasm bundle.
The output is four files in web/dist/: index.html, index.js, index.wasm and index.data. Serve them from any static host, or embed index.html in an <iframe>.
In the browser:
- ESC does nothing in the browser. The native ESC handler calls
exit(), which would stop the page. gfx_screen_sizereports 1280x720, so key6picks that size.- Mouse look only works while the cursor is over the canvas.
- Textured walls (BMP format)
- Floor and ceiling colors from map config
- Smooth movement with delta time
- Mouse look
- Minimap with ray visualization (toggle:
M,R) - Dynamic resolution switching (keys
1to6) - Subpixel edge blending (wall antialiasing)
- Collision detection with wall sliding
Raycasting algorithm: Supercover Bresenham grid traversal with fixed point arithmetic
Optimizations:
- Branchless step selection via arithmetic (
go_x = err < 0) - Corner tolerance check prevents rays clipping through diagonal walls
- Integer error accumulator instead of floating point DDA
| Key | Action |
|---|---|
WASD |
Move |
← → / Mouse |
Look |
M |
Toggle minimap |
R |
Toggle ray debug |
H |
Help menu |
1 to 6 |
Resolution presets |
ESC |
Quit (native only) |
- Lode Vandevenne, Raycasting Tutorial: https://lodev.org/cgtutor/raycasting.html
- Permadi, Raycasting Tutorial: https://permadi.com/1996/05/ray-casting-tutorial-table-of-contents/
- Fabien Sanglard, Game Engine Black Book: Wolfenstein 3D: https://fabiensanglard.net/gebbwolf3d/
- miniLibX documentation and examples
AI was used as a learning aid to understand the math behind the raycasting engine (Bresenham supercover traversal, camera plane projection, fisheye correction) and the miniLibX image and event API. All project code was written and reviewed by the authors.
Made with Jujutsu