A 3D raycasting engine implementation inspired by the classic Wolfenstein 3D game. This project creates a first-person perspective maze navigation experience using advanced raycasting algorithms and texture mapping.
- Overview
- Features
- System Architecture
- Installation
- Usage
- Map Configuration
- Controls
- Project Structure
- Build System
- Technical Details
- Testing
Cub3D is a 3D graphics engine built from scratch using the MiniLibX graphics library. The project demonstrates fundamental computer graphics concepts including raycasting, texture mapping, and real-time rendering. Players can navigate through maze-like environments with textured walls, creating an immersive 3D experience rendered in real-time.
- Real-time 3D rendering using raycasting algorithms
- Texture mapping with support for different wall textures based on direction
- Smooth player movement with collision detection
- Mouse and keyboard controls for navigation
- Configurable maps through .cub configuration files
- Performance optimized rendering at 60 FPS target
- Memory safe implementation with comprehensive cleanup
- Modular architecture for easy maintenance and extension
%% --- Cub3D Architectural Flowchart (Unstyled for Max Compatibility) --- %%
flowchart LR
%% === UTILITY SYSTEMS (Used by all phases) ===
subgraph UTILS [Utility Systems]
direction TB
ERROR_SYS["Error Handling<br><i>error_loggers.c</i>"]
DATA_UTILS["Data Structures<br><i>lines.c, string.c</i>"]
MATH_UTILS["Math Utilities<br><i>direction_utils.c</i>"]
end
%% === MAIN PROGRAM LIFECYCLE ===
subgraph ProgramLifecycle ["Program Lifecycle"]
direction LR
START(["./cub3D map.cub"]) --> MAIN["main.c<br>• Entry point & argument validation<br>• Initializes master <b>t_game</b> struct"]
MAIN --> PHASE1_SETUP
subgraph PHASE1_SETUP [PHASE 1: Configuration & Validation]
direction TB
READ_FILE["Read .cub file into lines<br><i>read_file.c</i>"]
PARSE["<b>Parse</b> config into memory<br><i>parser_*.c, tokenizer.c</i>"]
VALIDATE["<b>Validate</b> Map Integrity<br><i>map_validation.c (Flood-fill)</i>"]
READ_FILE --> PARSE --> VALIDATE
end
VALIDATE --> PHASE2_INIT
subgraph PHASE2_INIT [PHASE 2: Game World Initialization]
direction TB
WINDOW_INIT["Setup Window & Buffer<br><i>window.c</i>"]
TEXTURE_INIT["<b>Load Textures</b> from Paths<br><i>texture_loader.c</i>"]
PLAYER_INIT["Initialize Player State<br><i>player.c</i>"]
end
PHASE2_INIT --> PHASE3_LOOP
subgraph PHASE3_LOOP [PHASE 3: Interactive Game Loop]
direction LR
SETUP_HOOKS["Setup Event Hooks<br><i>events.c</i><br>Connects handlers to MLX engine"]
SETUP_HOOKS --> MLX_LOOP["MLX Engine Starts<br><i>mlx_loop()</i><br>Listens for events, schedules frames"]
subgraph "Input Handling (Event-Driven)"
direction TB
MLX_LOOP -- "User Input Event" --> INPUT_HANDLER["Input Handlers<br><i>events.c</i><br><b>Task:</b> Only sets boolean flags in <b>t_input</b>"]
INPUT_HANDLER --> EXIT_CHECK{"Exit Signal?"}
end
subgraph "Frame Rendering (Scheduled per Frame)"
direction TB
MLX_LOOP -- "Scheduled Frame Render" --> RENDER_FRAME["(1) Update Player State<br><i>player_movement.c</i><br>Reads <b>t_input</b> flags to calculate new position"]
RENDER_FRAME --> RAYCAST["(2) Render 3D Scene (DDA)<br><i>raycast.c, draw_utils.c</i>"]
RAYCAST --> DISPLAY["(3) Display Frame<br><i>mlx_put_image_to_window()</i>"]
DISPLAY --> FPS_LIMIT["(4) Limit Framerate<br><i>renderer.c</i>"]
end
end
EXIT_CHECK -- "Yes" --> CLEANUP["<b>Cleanup All Resources</b><br><i>cleanup.c</i><br>Frees all memory, destroys images & window"]
CLEANUP --> END([Program End])
end
%% === CROSS-CUTTING DEPENDENCIES ===
ProgramLifecycle -.-> UTILS
- GCC compiler with C99 support
- Make build system
- X11 development libraries (Linux)
- MiniLibX graphics library
# Clone the repository
git clone [repository-url]
cd Cub3D-main
# Build the project
make
# Build and run with default map
make run
# Build with debug information
make debug
# Clean build artifacts
make clean
make fclean
# Complete rebuild
make re
The project automatically handles MiniLibX linking. Ensure you have X11 development libraries installed:
# Ubuntu/Debian
sudo apt-get install libx11-dev libxext-dev
# Fedora/CentOS
sudo yum install libX11-devel libXext-devel
./cub3D [map_file.cub]
# Run with basic test map
./cub3D assets/maps/test_basic.cub
# Run with maze configuration
./cub3D assets/maps/test_maze.cub
# Run with large map
./cub3D assets/maps/test_large.cub
Maps are defined in .cub
files with the following format:
NO assets/textures/north_wall.xpm # North wall texture
SO assets/textures/south_wall.xpm # South wall texture
WE assets/textures/west_wall.xpm # West wall texture
EA assets/textures/east_wall.xpm # East wall texture
F 220,100,0 # Floor color (RGB)
C 225,30,0 # Ceiling color (RGB)
1111111111111111111111111
1000000000110000000000001
1011000001110000000000001
1001000000000000000000001
11111111101100000111000011111111
100000000011000001110111111111111
11110111111111011100000010001
11000000110101011100000010001
10000000000000001100000010001
11000001110101011111011110N0111
11111111 1111111 111111111111
1
: Wall0
: Empty space (walkable)N/S/E/W
: Player starting position and orientation
W
: Move forwardS
: Move backwardA
: Move leftD
: Move right
←
: Rotate camera left→
: Rotate camera right
ESC
: Exit game
Cub3D-main/
├── src/ # Source code
│ ├── core/ # Core application logic
│ ├── engine/ # Game engine components
│ ├── graphics/ # Graphics and rendering
│ │ ├── render/ # Rendering subsystem
│ │ ├── raycast/ # Raycasting engine
│ │ └── window/ # Window management
│ ├── io/ # Input/Output operations
│ │ ├── parsing/ # Configuration parsing
│ │ ├── lexer/ # Lexical analysis
│ │ └── events/ # Event handling
│ └── utils/ # Utility functions
├── include/ # Header files
├── assets/ # Game assets
│ ├── maps/ # Map configurations
│ └── textures/ # Wall textures
├── tests/ # Test files
├── config/ # Configuration templates
└── docs/ # Documentation
Target | Description |
---|---|
make |
Build the project |
make clean |
Remove object files |
make fclean |
Remove all build artifacts |
make re |
Clean rebuild |
make run |
Build and run with default map |
make test |
Run test scenarios |
make norm |
Check code style |
make valgrind |
Run with memory leak detection |
The Makefile supports different build configurations:
- Standard build: Optimized for general use
- Debug build: Includes debugging symbols and AddressSanitizer
- Release build: Optimized for performance
The engine uses a DDA (Digital Differential Analyzer) algorithm for efficient ray-wall intersection detection:
- Ray Initialization: Calculate ray direction for each screen column
- DDA Setup: Determine step direction and initial distances
- Wall Detection: Iteratively step through the grid until hitting a wall
- Distance Calculation: Compute perpendicular wall distance to avoid fisheye effect
- Texture Mapping: Map wall textures based on hit position and wall orientation
- Efficient memory management with object pooling
- Optimized texture sampling with integer arithmetic
- Frame rate limiting to maintain consistent 60 FPS
- Minimal memory allocations during render loop
- Cache-friendly data structures for better performance
- Input Processing: Handle keyboard and mouse events
- Player Update: Update player position and orientation
- Raycasting: Cast rays for each screen column
- Wall Rendering: Draw textured wall segments
- Floor/Ceiling: Fill remaining pixels with solid colors
- Buffer Display: Present the completed frame
# Run all test scenarios
make test
# Memory leak detection
make valgrind
# Code style validation
make norm
The project includes various test maps for different scenarios:
test_basic.cub
: Simple rectangular maptest_maze.cub
: Complex maze layouttest_large.cub
: Large-scale environmenttest_corridor.cub
: Long corridor testtest_minimum.cub
: Minimal valid map