diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..9d53e01 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,69 @@ +name: build + +on: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + build: + name: Build (mandatory + bonus) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install X11 dev libraries + run: | + sudo apt-get update + sudo apt-get install -y libx11-dev libxext-dev libbsd-dev zlib1g-dev + + - name: Install MinilibX to /usr/local + run: | + git clone --depth=1 https://github.com/42Paris/minilibx-linux.git /tmp/mlx + cd /tmp/mlx + make + sudo cp libmlx*.a /usr/local/lib/ + sudo cp mlx.h mlx_int.h /usr/local/include/ + sudo ldconfig + + - name: Build mandatory + run: make + + - name: Build bonus + run: make bonus + + - name: Verify binary + run: | + test -x ./cub3D + file ./cub3D + + - name: Clean + run: make fclean + + static-analysis: + name: Static analysis (cppcheck, advisory) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install cppcheck + run: | + sudo apt-get update + sudo apt-get install -y cppcheck + + - name: Run cppcheck on mandatory + run: | + cppcheck --enable=warning,performance,portability \ + --inline-suppr \ + --suppress=missingIncludeSystem \ + -I includes_mandatory \ + src_mandatory/ + + - name: Run cppcheck on bonus + run: | + cppcheck --enable=warning,performance,portability \ + --inline-suppr \ + --suppress=missingIncludeSystem \ + -I includes_bonus \ + src_bonus/ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4e8bbf5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,32 @@ +# Build artefacts +*.o +*.obj +*.a +*.so +*.dylib +*.dSYM/ +*.out + +# Object directories +obj_mandatory/ +obj_bonus/ + +# Binary +cub3D +cub3d + +# Editor / IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# macOS +.DS_Store +.AppleDouble +.LSOverride + +# Local MinilibX installs +mlx_linux/ +mlx_macos/ diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index be1f37b..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "files.associations": { - "cub3d.h": "c" - } -} \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..386a3cc --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Mukhammad Ibrokhimov, Ghazaleh Ansari + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile index 12975ae..3881300 100644 --- a/Makefile +++ b/Makefile @@ -133,8 +133,8 @@ else ifeq ($(OS), Darwin) endif # Include flags -MANDATORY_INCLUDES = -I$(INCLUDES_MANDATORY) -I$(LIBFT_DIR) $(INCLUDES_MLX) -BONUS_INCLUDES = -I$(INCLUDES_BONUS) -I$(LIBFT_DIR) $(INCLUDES_MLX) +MANDATORY_INCLUDES = -Iincludes_mandatory -I$(LIBFT_DIR) $(INCLUDES_MLX) +BONUS_INCLUDES = -Iincludes_bonus -I$(LIBFT_DIR) $(INCLUDES_MLX) # Colors for pretty output RED = \033[0;31m diff --git a/README.md b/README.md index 1a46e3a..290a85d 100644 --- a/README.md +++ b/README.md @@ -1,142 +1,106 @@ -# 🎮 cub3D - My First RayCaster +# cub3D -> *"Relive the golden age of gaming with your own Wolfenstein 3D-inspired raycaster!"* +[![build](https://github.com/MukhammadIbrokhimov/Cub3D/actions/workflows/build.yml/badge.svg)](https://github.com/MukhammadIbrokhimov/Cub3D/actions/workflows/build.yml) -[![42 School](https://img.shields.io/badge/42-School-000000?style=flat&logo=42&logoColor=white)](https://42.fr) -[![C](https://img.shields.io/badge/C-00599C?style=flat&logo=c&logoColor=white)](https://en.wikipedia.org/wiki/C_(programming_language)) -[![MinilibX](https://img.shields.io/badge/MinilibX-Graphics-red?style=flat)](https://github.com/42Paris/minilibx-linux) +A first-person raycasting engine written in C, inspired by Wolfenstein 3D. Walls are rendered by casting rays across the field of view with the DDA algorithm; each ray's hit point selects a texture column and draws a vertically-scaled slice. Runs on Linux (X11 / MinilibX) and macOS. Part of the 42 Berlin Common Core. -## 🚀 Overview +Built with [Ghazaleh Ansari](https://github.com/ghazalehans). -**cub3D** is a 3D graphics programming project that recreates the legendary **Wolfenstein 3D** experience using **ray-casting** techniques. This project pays homage to the world's first FPS game (1992) by Id Software, while teaching fundamental 3D graphics programming concepts. +## Features -Navigate through mysterious mazes from a first-person perspective, where mathematics meets visual artistry to create the illusion of three-dimensional space on a 2D screen. +### Mandatory +- DDA-based raycasting with fish-eye correction +- Textured walls with per-direction textures (N / S / E / W) +- Configurable floor and ceiling colours (RGB) +- Map parser for the `.cub` format with enclosure validation via flood fill +- Smooth WASD movement and arrow-key rotation +- Proper exit cleanup (MLX windows, images, memory) -## ✨ Features +### Bonus +- Minimap overlay with player position and ray visualisation +- Extra parsing paths and texture-coordinate helpers +- Additional maps (`cray`, `hard`, `medium`, `no_gravity`, `simple`, `zelij`) with custom Berlin-themed textures -### 🎯 Core Functionality -- **Real-time ray-casting engine** - Experience smooth 3D rendering -- **Texture mapping** - Dynamic wall textures based on cardinal directions -- **First-person navigation** - WASD movement with arrow key rotation -- **Interactive environment** - Explore mazes with realistic perspective -- **Custom map support** - Load your own maze configurations -- **Optimized rendering** - Efficient graphics pipeline for smooth gameplay +## Architecture -### 🎨 Visual Elements -- **Directional textures** - Unique wall appearances for North, South, East, West -- **Customizable colors** - Configurable floor and ceiling aesthetics -- **Smooth animations** - Fluid movement and rotation mechanics -- **Window management** - Professional GUI handling with proper cleanup - -### 🗺️ Map System -- **Flexible parsing** - Support for custom `.cub` map files -- **Robust validation** - Comprehensive error handling and map verification -- **Simple format** - Easy-to-create maze layouts using basic characters -- **Boundary detection** - Automatic wall collision and map boundary enforcement +``` +.cub file ─► parser ─► validated map + textures + spawn + │ + ▼ + keyboard ─► game loop ─► raycaster (DDA) ─► renderer ─► MLX +``` -## 🛠️ Technical Implementation +- **Parser** (`src_mandatory/parsing/`) — reads the `.cub` header, loads textures, extracts map dimensions, then runs flood fill from the spawn point to prove the map is fully enclosed. +- **Raycaster** (`src_mandatory/raycasting/raycasting.c`) — classic DDA: compute `delta_dist` and `side_dist`, step along the grid until a wall is hit, record side and distance. +- **Renderer** (`src_mandatory/raycasting/rendering.c`, `drawing.c`) — translates ray distance into a scaled vertical slice and draws it column-by-column into an MLX image buffer. -🏗️ Architecture -├── Ray-casting Engine → Core 3D rendering mathematics -├── Texture Pipeline → Graphics memory and image processing -├── Input Management → Real-time keyboard/mouse handling -├── Map Parser → Configuration file processing -└── Game Loop → Event-driven program lifecycle +## Build and run -### 📋 Technologies Used -- **Language:** C (following 42 School Norm) -- **Graphics:** MinilibX library -- **Mathematics:** Linear algebra, trigonometry, vector calculations -- **Memory Management:** Manual heap allocation with leak prevention -- **Build System:** Custom Makefile with proper dependency management +### Linux -## 🎮 Controls +```bash +sudo apt-get install -y libx11-dev libxext-dev libbsd-dev zlib1g-dev +# MinilibX auto-detected in mlx_linux/ if present, otherwise system-installed +make # builds cub3D (mandatory) +make bonus # builds with minimap +./cub3D maps/mandatory/sample.cub +``` -| Key | Action | -|-----|--------| -| `W` `A` `S` `D` | Move through the maze | -| `←` `→` | Rotate camera left/right | -| `ESC` | Exit program | +### macOS -## 🗂️ Map Configuration +MinilibX for macOS is expected in `mlx_macos/` at the repo root. If you don't have it, grab the 42 copy, or let `make` print the expected location. -Create your own adventures with simple `.cub` files: -NO ./textures/north_wall.xpm -SO ./textures/south_wall.xpm -WE ./textures/west_wall.xpm -EA ./textures/east_wall.xpm -F 220,100,0 # Floor color (RGB) -C 225,30,0 # Ceiling color (RGB) -111111111 -100000001 -101010101 -100000001 -1000N0001 -111111111 +```bash +make +./cub3D maps/mandatory/sample.cub +``` -## 🚀 Getting Started +## Controls -### Prerequisites -- GCC compiler with `-Wall -Wextra -Werror` flags -- MinilibX library -- Math library (`-lm`) -- X11 development libraries (Linux) +| Key | Action | +|---|---| +| `W` / `A` / `S` / `D` | Move forward / strafe left / back / strafe right | +| `←` / `→` | Rotate view | +| `ESC` | Exit | -### Installation & Usage +## Map format -```bash -# Clone the repository -git clone https://github.com/yourusername/cub3D.git -cd cub3D -``` +A `.cub` file is a textures-and-colours header followed by a grid of `0` (empty) / `1` (wall) / `N S E W` (spawn facing direction): -# Compile the project -``` -make ``` - -# Run with a map file -./cub3D maps/sample.cub -Building -```make # Compile the project -make clean # Remove object files -make fclean # Remove all generated files -make re # Recompile everything -make bonus # Compile with bonus features +NO ./textures/north_wall.xpm +SO ./textures/south_wall.xpm +WE ./textures/west_wall.xpm +EA ./textures/east_wall.xpm +F 220,100,0 +C 225,30,0 + +1111111111 +1000000001 +100N000001 +1000000001 +1111111111 ``` -🎯 Project Goals -This project serves as an introduction to: - -3D Graphics Programming - Understanding ray-casting and rendering pipelines -Mathematical Applications - Practical use of geometry and trigonometry -Game Development - Real-time graphics and user interaction -System Programming - Memory management and performance optimization -Collaborative Development - Team-based software engineering practices -🏆 Bonus Features +The parser enforces: exactly one spawn, fully enclosed by walls, all four textures present, valid RGB colours. -🎯 Wall Collisions - Realistic movement boundaries -🗺️ Minimap System - Real-time navigation aid -🚪 Interactive Doors - Open/close mechanics -🎭 Animated Sprites - Dynamic game elements -🖱️ Mouse Controls - Enhanced camera manipulation +## Constraints -👥 Team Development -This project is designed for collaborative development between two programmers: +From the 42 subject: -🎨 Graphics Engineer - Ray-casting, rendering, textures -🎮 Game Systems Engineer - Input handling, parsing, game logic +- C, compiled with `cc -Wall -Wextra -Werror` +- 42 norm: 80-char lines, ≤25-line functions, no globals +- Only MinilibX, libc, and maths functions allowed +- No leaks (including on error paths and on exit) +- Map validation must reject malformed input with a clear error -🎓 Learning Outcomes -By completing this project, developers gain hands-on experience with: +## What was technically hard -Low-level graphics programming -Mathematical problem-solving in software -Real-time system constraints -Memory-efficient algorithm design -Cross-platform development considerations +- **Flood-fill enclosure check**: proving the map is closed in the face of irregular shapes, odd spacing, and trailing characters. +- **Texture selection per ray hit**: deciding which of the four textures applies based on which side of the grid cell was hit, then mapping pixel columns correctly without stretching. +- **MLX memory ownership**: every image and window handle must be destroyed before exit; a single stray handle causes a visible leak. +- **Avoiding fish-eye distortion**: using perpendicular distance instead of Euclidean distance when computing wall-slice height. -📄 License -This project is part of the 42 School curriculum. Educational use only. +## Authors -Built with ❤️ by aspiring game developers at 42 School +[Mukhammad Ibrokhimov](https://github.com/MukhammadIbrokhimov) and [Ghazaleh Ansari](https://github.com/ghazalehans).