This project is inspired by the world-famous Wolfenstein 3D game.
The goal is to make a dynamic view inside a maze, in which you’ll have to find your way.
Raycasting is a rendering technique to create a 3D perspective in a 2D map. Back when computers were slower it wasn't possible to run real 3D engines in realtime, and raycasting was the first solution. Raycasting can go very fast, because only a calculation has to be done for every vertical line of the screen. The most well known game that used this technique, is of course Wolfenstein 3D.
Note: Raycasting is not the same as raytracing! Raycasting is a fast semi-3D technique that works in realtime even on 4MHz graphical calculators, while raytracing is a realistic rendering technique that supports reflections and shadows in true 3D scenes, and only recently computers became fast enough to do it in realtime for reasonably high resolutions and complex scenes.
The cub3d
executable receives as a single argument, the map file we read, which must be of .cub
filetype.
The file must follow these rules:
- There must be header lines before the actual map containing the following:
- At least a line containing
NO
,SO
,EA
andWE
followed by a valid path to an xpm image - A line starting with
F
(floor) orC
(ceiling) followed by a color in RGB separated by commas
- At least a line containing
- Only
1
(wall),0
(floor), and eitherN
,S
,E
orW
(Player starting position looking at North, South, East or West), will be accepted characters in our map. - The map may not be rectangular, but it must be surrounded by walls
- Spaces are allowed but the player cannot walk on them, thus every space must also be closed/surrounded by walls
- There must be a single player on the map
To calculate the distance between the player and the nearest wall, we can use the following algorithm:
Attribute | Description | Value |
---|---|---|
FOV | The field of view of the player | 60º |
HFOV | Half of the player's FOV | 30º |
Player's position | Center of the square where the player is | (int)(player_x + 0.5), (int)(player_y + 0.5) |
Ray angle | Angle of the player view's direction | N (270º), S (90º), E (0º), W (180º) |
Ray increment angle | Angle difference between one ray and the next one | 2 * HFOV / window_width |
Precision | Size of 'steps' taken every iteration | 50 |
Limit | Limit of the distance the player can view | 11 |
ray.x += ray_sin;
ray.y += ray_cos;
distance = sqrt(powf(x - pl.x - 0.5, 2.0) + powf(y - pl.y - 0.5, 2.0));
This algorith is repeated window_width
times.
This distance is really helpful to calculate the height of the wall height:
wall_height = (window_height / (1.5 * distance));