📣 Rules
💥 New concept: Raycasting
🌈 Textures
🔥 Bonus
🕹️ Time to play
The aim of the cub3D proyect is to create a 3D game using the raycasting technique which is a rendering method implemented in the world-famous Wolfenstein 3D game. This was a group proyect and I had the honor to repeat with @madebypixel02 :)
This 3D game must follow the following rules:
- The executable cub3D must receive at least one argument, a map.
- The map is a .cub file
- The first few lines must contain a direction, written as
NO
,SO
,WE
,EA
, followed by a path to an .xpm image. If one of these directions appears more than once, the image or texture is updated if the new path is valid. - After the textures and an empty line, the RGB color for the floor and ceiling is shown as
F
orC
followed by the RGB coordinates separated by commas. - Finally, the map is display.
- These are the possible characters:
0
(floor),1
(wall) andN
,S
,W
,E
(player's view direction). Additionally, for the bonus we havec
(close door) ando
(open door). - The map must be surrounded by walls, even the empty spaces.
So a valid map would be seen as this one:
NO textures/wall_1.xpm
NO textures/wall_1.xpm
SO textures/wall_2.xpm
WE textures/wall_3.xpm
EA textures/wall_3.xpm
F 255,113,39
C 51,198,227
11111111111111111111111111111
11111111110000000000000000011111
10110000011100000000000111111
100000000110000011111111111
11111111111111011100000010001
11111111000001111100000010001
1000001 100000001100011111111
11110000111101000N00000011111
11111111111111111111111111111
11111111111111111111111111111
10000000111100010000000001001
100000001 100110101110000001
10000000111110000001 10100001
11111111111111111111 11111111
- The
W
,A
,S
andD
keys move up, down, left and right the player's point of view. - The
left
andright
arrow keys rotate the field of view of the player. - Pressing
ESC
or the red cross on the window's frame must close the window and quit the program cleanly.
Additionally for the bonus part, if you press the E
key in front of a door you can open or close it.
Raycasting is a rendering technique to create a 3D perspective in a 2D map. The logic behind RayCasting is to throw rays in the direction of the player view. Basically, we need to check the distance between the player and the nearest wall (i.e. the point the ray hits a wall) to caculate the height of the vertical lines we draw.
To calculate the distance between the player and the nearest wall, we can use the following algorithm:
- Initialize some basic attributes needed for the projection:
- From the the player's position, we move the ray forward incrementing the x's and y's coordinates of the ray.
ray.x += ray_cos;
ray.y += ray_sin;
where ray_cos
and ray_sin
are of the form:
ray_cos = cos(degree_to_radians(ray_angle)) / g->ray.precision;
ray_sin = sin(degree_to_radians(ray_angle)) / g->ray.precision;
-
Repeat step 2 until we reach the limit or we hit a wall.
-
Calculate the distance between the player's and the ray's position using the euclidean distance:
distance = sqrt(powf(x - pl.x - 0.5, 2.) + powf(y - pl.y - 0.5, 2.));
- Fix fisheye
distance = distance * cos(degree_to_radians(ray_angle - g->ray.angle))
This algorith is repeated window_width times, i.e. in every iteration we increment the angle until we have been through all the field of view. This distance is really helpful to calculate the height of the wall height:
wall_height = (window_height / (1.5 * distance));
One last thing we need to do is to read pixels (x,y)
from a texture image i
to get the colors of the wall.
x = (int)(i->width * (g->x + g->y)) % i->width;
// y = image height
color = my_mlx_pixel_get(i, x, y);
Once we know the wall height and all the colors, we have everything we need to draw the ceiling, the wall and the floor.
- Ceiling: from screen top to screen half height minus wall height
- Wall: from half height minus wall height to half height plus wall height
- Floor: from half height plus wall height to screen botton
-
Wall collisions Once the player come accross a wall, instead of stopping in front of it, the player can move in the
x
ory
direction. -
Minimap As the name says, the minimap is a small 2D map of the maze that shows the players' path on the map.
-
Doors
The doors appear in the map as ac
for a close door and ao
for an open door. If a ray in the field of view of the player hits a door, you can open or close it pressingE
key. -
Animations Our animated sprites are the walls. In order to do that, we read multiple textures path in the file and we save them in a linked list. Iterating over the list, the wall textures is changed for the next one.
-
Rotation with mouse
There is an event on theminilibx
library that tell us the position of the mouse. If the position changes, the field of view of the players changes accordingly.
Here are a few samples of how our maps look
1.cub
2.cub
pac.cub
pac2.cub
To check some of our favorite layouts, see MAPS.md