Welcome to cub3D, a project that explores the fundamentals of 3D graphics by building a "Wolfenstein 3D-like" game engine from the ground up. This endeavor, part of the 1337/42 School curriculum, involves parsing a 2D map and rendering it into an immersive, first-person 3D experience using the ray casting technique.
- 3D Graphics Engine: Renders a 3D maze from a first-person perspective using ray casting.
- Texture Mapping: Applies textures to walls for a more immersive environment.
- Player Movement: Full range of movement including forward, backward, and strafing, plus camera rotation.
- Map Parsing: Robust parsing of
.cubfiles that define the game world. - Error Handling: Graceful management of invalid map configurations.
- Mini-map: An on-screen display of the player's position and the immediate surroundings.
- Mouse Control: Modern camera controls using the mouse for smoother navigation.
- Wall Collisions: Prevents the player from walking through walls.
- A C compiler (e.g.,
cc,clang). - The
makeutility. - This project is developed for macOS and relies on the
minilibx(OpenGL version) and AppKit framework.
-
Clone the repository:
git clone https://github.com/elmehdi-elgarouaz/cub3d.git cd cub3d -
Build the project:
- For the mandatory version:
make
- For the bonus version (includes mini-map and mouse control):
make bonus
- For the mandatory version:
-
Launch the game: You must provide a map file from the
Mandatory/mapsorBonus/mapsdirectory as an argument../cub3D Mandatory/maps/map1.cub
For the bonus version:
./cub3D_bonus Bonus/maps/map1_bonus.cub
The engine's architecture is a classic CPU-GPU collaboration, broken down into three main phases. This graph illustrates the entire process from running the program to rendering a single frame.
graph TD
subgraph "Phase 1: The Blueprint (CPU-Heavy Parsing)"
A["User runs './cub3D map.cub'"] --> B{"macOS Kernel"}
B --> C["dyld (Dynamic Linker) loads program"]
C --> D["Loads Frameworks (AppKit, OpenGL) into memory"]
D --> E["main() function begins"]
E --> F["Parsing functions are called"]
F -- "Opens & reads the .cub file" --> G["Validate all identifiers and map data"]
G --> H["Success: a complete 't_game' data struct is created in RAM"]
end
subgraph "Phase 2: Sending Materials (CPU -> GPU Hand-off)"
H --> I["mlx_init() is called"]
I -- "Uses AppKit to connect to the window server" --> J["mlx_new_window() creates a window on screen"]
J --> K["mlx_xpm_file_to_image() is called for each texture"]
K -- "CPU sends pixel data to GPU via OpenGL commands" --> L["Textures are now stored in the GPU's VRAM"]
end
subgraph "Phase 3: The Render Loop (The CPU-GPU Dance)"
L --> M["mlx_loop_hook() registers the main render function"]
M --> N{"Render Loop Begins"}
subgraph "One Frame"
N --> O["Input: Check for key presses (W, A, S, D, Arrows)"]
O --> P["Update (CPU): ft_move_player() updates player's x, y, and angle in RAM"]
P --> Q["Calculate (CPU): ft_cast_rays() performs all the math to determine what to draw"]
Q --> R["Prepare Draw Commands (CPU): ft_draw_all() tells the GPU what color each pixel of the wall slice should be"]
R --> S["Execute (GPU): The GPU receives commands via OpenGL/Metal and uses its shaders to rapidly draw the entire scene to an off-screen image buffer"]
S --> T["Display: mlx_put_image_to_window() puts the final, completed image on the screen"]
T --> N
end
end
style A fill:#D1FAE5,stroke:#065F46
style H fill:#D1FAE5,stroke:#065F46
style L fill:#FEF9C3,stroke:#713F12
style S fill:#DBEAFE,stroke:#1E40AF
style T fill:#DBEAFE,stroke:#1E40AF
At its core, the rendering engine uses a Digital Differential Analyzer (DDA) algorithm. For each vertical slice of the screen, a ray is cast from the player's position. The algorithm calculates the distance to the nearest wall by checking for intersections with both horizontal and vertical grid lines. The shortest distance is then used to determine the height of the wall to be drawn on the screen. A key challenge is correcting the "fisheye" effect, where walls can appear curved. This is solved by adjusting the ray's distance using the cosine of the angle relative to the player's view, ensuring a distortion-free projection.
This project was brought to life by the collaborative efforts of two passionate developers.
Youssef Mazini |
El Mehdi El Garouaz |
|---|---|
| 🐙 GitHub |
🐙 GitHub |
