Skip to content

zelhajou/42cursus-cub3D

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

85 Commits
 
 
 
 
 
 
 
 

Repository files navigation

ascii-text-art

cub3D

Table of Contents

Project Overview

Welcome to our cub3d project! As a team, we'll be diving into the exciting world of raycasting and basic 3D graphics programming. Our main goal is to create a simple 3D maze game from scratch using raycasting techniques.

Summary

This project is inspired by the world-famous Wolfenstein 3D game, which was the first FPS ever. It is a remarkable technique to explore, and a great opportunity to create a game with a good design and a nice user interface.

cool-guys-1992-small

Developed by id Software and published by Apogee Software, Wolfenstein 3D was released in 1992. It was a revolutionary game that popularized the FPS genre and helped establish the PC as a gaming platform.

Playable Wolfenstein 3D

Project Goals

  1. Raycasting Engine: Develop a raycasting engine to render a 3D world from a first-person perspective.
  2. Parsing Configuration File: Read and parse a configuration file (.cub) to define our game settings, including map layout, textures, and other parameters.
  3. Texture Mapping: Apply textures to walls and potentially the floor and ceiling to enhance our game's visual appearance.
  4. Player Movement and Controls: Implement controls to allow the player to move within the 3D world, including basic movement (e.g., forward, backward, strafing) and rotation.
  5. Basic Game Mechanics: Create a playable game where the player can navigate through a maze-like environment, interact with objects, and complete objectives.
  6. Error Handling and Optimization: Implement robust error handling to handle invalid input and prevent crashes. Optimize our code for performance to ensure smooth gameplay.

Project Requirements

  • Language: We'll be using C for this project.
  • Libraries: We can use standard libraries like math. External libraries like minilibx are allowed for graphics rendering.
  • Map Configuration: Our game should read a map configuration file (.cub) that defines game settings, including map layout, textures, colors, and more.
  • Graphics: The game must render a 3D perspective view of the game world using raycasting techniques. Textures should be applied to walls to enhance the visual appearance.
  • Controls: Implement controls to allow the player to move and navigate within the 3D world using keyboard input.
  • Bonus Features: While not required, implementing additional features like a minimap, HUD (Heads-Up Display), or more complex game mechanics can earn us extra points.

Screenshots and Demos of our project

Screen Shot 2024-05-09 at 12 22 47 PM Screen Shot 2024-05-09 at 12 24 31 PM
Screen Shot 2024-05-09 at 12 47 45 PM Screen Shot 2024-05-09 at 12 40 14 PM
freecompress-Screen.Recording.2024-05-10.at.3.12.45.PM.mp4

Team Development Steps

As a team, we'll be tackling the cub3d project in a systematic manner to ensure a successful outcome. Here's our proposed development roadmap:

1. Project Setup

Set up the project repository, establish communication channels, and assign roles.

  • Create Repository: Set up a Git repository for the project.
  • Establish Communication: Choose communication tools (Discord) for team collaboration.
  • Assign Roles: Define roles and responsibilities for each team member.

2. Parsing Configuration File

Implement the code to read and parse the configuration file (.cub) to extract game settings.

  • Read File: Open and read the .cub configuration file.
  • Validate Data: Check for valid map settings, resolution, textures, etc.
  • Parse Data: Extract and store relevant information from the configuration file.

3. Initialize Graphics

Set up the graphics rendering engine using the minilibx library.

  • Initialize Minilibx: Set up the Minilibx library for graphics rendering.
  • Create Window: Create a window for rendering the game.
  • Setup Buffer: Set up a buffer for rendering pixels to the window.

4. Raycasting Engine

Develop the raycasting engine to render a 3D perspective view of the game world.

  • Initialize Ray: Start with the player's position and direction.
  • Cast Rays: Cast rays from the player's position to calculate distances to walls.
  • Calculate Wall Strips: Determine the height and texture of each wall strip to draw.

5. Texture Mapping

Apply textures to walls to enhance the visual appearance of the game.

  • Load Textures: Load wall and sprite textures from files.
  • Implement Texture Mapping: Apply textures to the rendered walls.

6. Player Movement and Controls

Implement controls to allow the player to move and navigate within the 3D world.

  • Handle Input: Implement controls for player movement (e.g., WASD for movement, arrow keys for rotation).
  • Update Player Position: Update the player's position based on input and collision detection.

7. Rendering Game World

Render the game world using the raycasting results and textures.

  • Draw Walls: Render the walls of the 3D world using the raycasting results.
  • Draw Floor and Ceiling: Render the floor and ceiling of the 3D world.
  • Draw Sprites: Implement sprite rendering if necessary.

8. Error Handling and Cleanup

Implement error handling to prevent crashes and ensure a smooth user experience.

  • Error Checks: Implement error handling to catch and handle any runtime errors.
  • Memory Cleanup: Free allocated memory and resources.
  • Close Window: Properly close the graphics window when exiting the game.

9. Optimization and Refactoring

Optimize the code for performance and refactor as needed for better readability.

  • Optimize Raycasting: Improve raycasting performance if necessary.
  • Refactor Code: Clean up and organize the code for better readability and maintainability.

10. Bonus Features (Optional)

Implement additional features to enhance the game experience and earn extra points.

  • Add Features: Implement additional features like a minimap, HUD, or more complex game mechanics.
  • Testing: Thoroughly test the game to ensure all features work as expected.

Project Structure

The project will be structured as follows:

cub3d/
│
└── src                        # Source code files
│   ├── parsing                # Functions for parsing the configuration file
│   │   ├── color
│   │   ├── config
│   │   ├── map
│   │   └── texture
│   ├── rendering               # Functions for rendering the 3D world
│   └── utils                   # Utility functions
│
├── includes                    # Header files
│   ├── cub3d.h
│   └── engine.h
│
├── assets/
│   ├── textures/               # Directory for storing texture files (.xpm or .png)
│   └── maps/                   # Directory for storing map configuration files (.cub)
│
├── libft/                      # If you're using your own libft library
│   ├── libft.a                 # Compiled library
│   └── includes/               # Header files for libft
│
└── Makefile                    # Makefile for compiling the project

In this structure:

  • src/: Contains the source code files for the project.
    • parsing/: Functions for parsing the configuration file.
      • color/: Functions for parsing and validating color settings.
      • config/: Functions for parsing and validating configuration settings.
      • map/: Functions for parsing and validating map settings.
      • texture/: Functions for parsing and validating texture settings.
    • rendering/: Functions for rendering the 3D world.
    • utils/: Utility functions for common tasks.
  • includes/: Contains header files for the project.
    • cub3d.h: Main header file for the project.
    • engine.h: Header file for the graphics rendering engine.
  • assets/: Directory for storing texture files (.xpm or .png) and map configuration files (.cub).
    • textures/: Directory for storing texture files.
    • maps/: Directory for storing map configuration files.
  • libft/: If you're using your own libft library, this directory contains the compiled library and header files.
  • Makefile: Makefile for compiling the project.

I. Project Setup

Step 1: Setup

Create the project directory structure and necessary files.

mkdir -p cub3d/src/main cub3d/src/parsing cub3d/src/rendering cub3d/src/utils
mkdir -p cub3d/includes cub3d/assets/textures cub3d/assets/maps

Step 2: Create Files

Create the main source files and header file for the project.

touch cub3d/src/main/main.c
touch cub3d/src/parsing/parse.c
touch cub3d/src/rendering/render.c
touch cub3d/src/utils/utils.c
touch cub3d/includes/cub3d.h
touch cub3d/assets/textures/.gitkeep
touch cub3d/assets/maps/.gitkeep
touch cub3d/Makefile

II. Parsing Configuration File

The first step in our project is to read and parse the configuration file (.cub) that defines our game settings. The configuration file contains information about the map layout, textures, colors, resolution, and other parameters needed to set up the game environment.

Here's an example of a simple configuration file:

NO ./assets/textures/north.png
SO ./assets/textures/south.png
WE ./assets/textures/west.png
EA ./assets/textures/east.png

F 220,100,0
C 0,0,100

 1111111        111111111
110000011      10000000001
100000001     1000000000001
 1000001     100000000000001
  11011      1000000000000001
   101        1000000100000001
   101         100001 100000001
   101111111111100000100000001
   10000000000000000000000001
   1011111111111000000000001
   101         100000000001
   101        100000000001
  11011      100000000001
 1000001     1000000N0001
100000001     10000000001
110000011      1000000001
 1111111        111111111

In this example, the configuration file specifies the following settings:

  • Textures:
    • North wall texture: ./assets/textures/north.png
    • South wall texture: ./assets/textures/south.png
    • West wall texture: ./assets/textures/west.png
    • East wall texture: ./assets/textures/east.png
  • Floor Color: RGB value (220,100,0)
  • Ceiling Color: RGB value (0,0,100)
  • Map Layout:
    • 1: Wall
    • 0: Empty space
    • N, S, W, E: Player starting position and direction

Our task is to read and parse this configuration file to extract these settings and use them to set up the game environment.

To achieve this, we'll need to implement functions to:

  • Open and read the configuration file.
  • Parse the data to extract relevant settings.
  • Validate the data to ensure it's in the correct format.
  • Store the settings in appropriate data structures for later use.

Map requirements

  1. Map Elements: The map must contain only the following elements:
    • 0: Empty space
    • 1: Wall
  2. Map Shape: The map must be surrounded by walls (1) on all sides. The map's shape can be a rectangle, but it can also have holes inside it.
  3. Valid Characters: Only the map elements mentioned above and spaces are valid characters in the map. Any other character is considered invalid.
  4. Starting Position: The map must have a starting position for the player. This starting position must be represented by one of the following characters:
    • N: North
    • S: South
    • W: West
    • E: East

Prsing and Storing the Configuration File

To parse the configuration file, we'll need to:

  1. Read the File: Open and read the configuration file line by line.
  2. Parse the Data: Extract relevant settings from each line of the file.
  3. Store the Data: Store the settings in appropriate data structures for later use.

Here's a basic outline of the steps involved in parsing the configuration file:

  1. Open File: Open the configuration file for reading using the open system call.
  2. Read Lines: Read each line of the file using the get_next_line function.
  3. Parse Data: Parse the data from each line to extract relevant settings (e.g., textures, colors, map layout).

To store the configuration settings, we'll define a t_config structure to hold the extracted data:

typedef struct s_config
{
    char    *no_texture;
    char    *we_texture;
    char    *so_texture;
    char    *ea_texture;
    int     floor_color;
    int     ceiling_color;
    char    **map;
    char    **map_copy;
    size_t  map_width;
    size_t  map_height;
    int     map_started;
}    t_config;

The t_config structure contains fields to store the configuration settings extracted from the configuration file. We'll use this structure to store the textures, colors, and map layout.

└── src
    ├── parsing
    │   ├── color
    │   │   ├── color_parsing.c
    │   │   └── color_validation.c
    │   ├── config
    │   │   ├── config_file_parsing.c
    │   │   └── config_validation.c
    │   ├── map
    │   │   ├── map_parsing.c
    │   │   └── map_validation.c
    │   └── texture
    │       ├── texture_parsing.c
    │       └── texture_validation.c

The color, config, map, and texture directories contain functions for parsing and validating the color, configuration, map, and texture settings, respectively. Each directory contains two files: one for parsing the data and one for validating it.

By parsing and storing the configuration file, we'll be able to extract the game settings needed to set up the game environment.

III. Initialize Graphics

The next step in our project is to initialize the graphics rendering engine using the minilibx library. The Minilibx library is a simple graphics library that provides functions for creating windows, drawing pixels, and handling user input.

To set up the graphics rendering engine, we'll need to:

  • Initialize the Minilibx library.
  • Create a window for rendering the game.
  • Set up a buffer for rendering pixels to the window.
  • Handle user input for player controls.

Here's a basic outline of the steps involved in setting up the graphics rendering engine:

  1. Initialize Minilibx: Start by initializing the Minilibx library to set up the graphics environment.
  2. Create Window: Create a window for rendering the game using the mlx_new_window function.
  3. Setup Buffer: Set up a buffer for rendering pixels to the window using the mlx_new_image function.
  4. Handle User Input: Implement functions to handle user input for player controls (e.g., movement, rotation).

By setting up the graphics rendering engine, we'll be able to display the game world and interact with it using player controls.

Raycasting Engine

Texture Mapping

Player Movement and Controls

Rendering Game World

Error Handling and Cleanup

Bonus Features

Resources

Researched Topics

[Mathematics]

Trigonometry: Essential for dealing with angles and rotations in 3D space. You'll frequently use trigonometric functions like sine, cosine, and tangent to calculate positions and angles.

Trigonometry is a branch of mathematics that deals with the relationships between the sides and angles of triangles. It is essential for understanding 3D graphics programming, as it helps you calculate positions, rotations, and other transformations in 3D space.

linear algebra: Linear algebra is a branch of mathematics that deals with vectors, matrices, and linear transformations. It is essential for understanding 3D graphics programming, as it helps you represent and manipulate objects in 3D space.

Vectors and Matrices: Vectors and matrices are fundamental concepts in 3D graphics programming. You'll use them to represent positions, directions, transformations, and more.

Vector and Matrix is a very important concept in computer graphics. It is used to represent the position, direction, and transformation of objects in 3D space. It is also used to represent the color of the object, the texture of the object, and the light source in the scene.

Geometry: Geometry is the branch of mathematics that deals with shapes, sizes, and properties of space. It is essential for understanding 3D graphics programming, as it helps you calculate positions, angles, and distances in 3D space.

Calculus: Calculus is a branch of mathematics that deals with rates of change and accumulation. It is essential for understanding 3D graphics programming, as it helps you calculate velocities, accelerations, and other dynamic properties of objects in 3D space.

[Computer Graphics]

Computer graphics is a field of study that focuses on the creation, manipulation, and rendering of images using computers. It is essential for understanding how to create 2D and 3D graphics, animations, and visual effects.

[Raycasting]

Raycasting is a rendering technique used to create a 3D perspective view of a scene from a 2D map. It is commonly used in video games to simulate 3D environments using 2D graphics.

[MinilibX]

[42 students articles]