Compare commits

...

26 commits

Author SHA1 Message Date
Theo Champion
02940e9ecf fix: readded matrix allcation (oopsy daisy) 2025-07-31 14:05:30 +02:00
Theo Champion
05e24d19f9 cleanup: moved initialization code from main() to a separate file 2025-07-31 13:41:16 +02:00
Theo Champion
7b0d05532c cleanup(raycast): renamed render.c to walls.c to not confuse it with the actual renderer 2025-07-31 13:40:38 +02:00
e625e254f7
feat: allocate screen_matrix on the heap 2025-07-31 13:38:49 +02:00
Theo Champion
8d0a6d841b feat(README): Added warning regarding certain valgrind errors 2025-07-31 12:20:19 +02:00
ca5fa86d10
fix: prevent zero-division in rare cases 2025-07-31 11:59:17 +02:00
Theo Champion
6fe6eb0a9a norm: removed unused code 2025-07-31 11:30:21 +02:00
Theo Champion
3cc73fc8ce feat: added colors depending on cardinal facing 2025-07-31 11:25:09 +02:00
Theo Champion
fb57ef253a docs: documented ray struct 2025-07-30 16:46:31 +02:00
Theo Champion
f21b8dc448 fix: fixed norme 2025-07-30 16:40:33 +02:00
Theo Champion
e28cd1c85b feat: readded minimap 2025-07-30 16:35:39 +02:00
Theo Champion
5281fe6abd feat: made 3d... for the cub3d 2025-07-30 16:25:41 +02:00
Theo Champion
077659cd25 feat: Added raycaster (concept only no drawing yet)
Almost copy pasted from https://github.com/herbievine/42/blob/main/cub3d
but it's also copied from Lodev's ressource
2025-07-30 13:34:36 +02:00
Theo Champion
7c42208d20 dev: added ray structure 2025-07-30 12:07:45 +02:00
Theo Champion
a9b5fbd370 chore(map): changed spawn angle to north for easier debugging of angles: 2025-07-29 20:15:20 +02:00
Theo Champion
788f248c5e fix: norme compliance 2025-07-29 20:13:43 +02:00
Theo Champion
b6eeea5e9f feat(player): reimplemented angles 2025-07-29 19:50:23 +02:00
Theo Champion
e46f199606 fix: forgot to add header file 2025-07-29 15:03:10 +02:00
Theo Champion
2e1838e0bd removal(player): removed old angle code as it's incompatible with new methods 2025-07-29 15:02:40 +02:00
Theo Champion
faf5127829 feat(player): redid all the movement code more details in desc
- had to tamper at init with the map pointer to allow player to move
- tweaked movement speed
- allowed for multiple keys to be pressed at the same time
- added collisions
- had to modify minimap code because it segfaulted due to old code
2025-07-29 15:01:31 +02:00
Theo Champion
ac94e9e937 fix(player init): deleted old init_player function in favor of the new
one
2025-07-29 13:33:58 +02:00
Theo Champion
9c710c13e3 fix: removed stash conflict 2025-07-29 13:33:04 +02:00
Theo Champion
1626b1d9da fix(hooks): Reworked keypresses events
Keypresses (along with keyreleases) events are now using booleans, a
function in the game loop will apply various changes as the key are
pressed. By default every boolean are set to false
2025-07-29 12:33:58 +02:00
Theo Champion
fa3cb8da4a fix(player): reworked angles for player and added player initialization 2025-07-29 12:29:59 +02:00
Theo Champion
6c5a15915f removal: commented old raycaster loop 2025-07-29 12:13:05 +02:00
Theo Champion
5161bc4e49 feat(maps): added new map for easier testing of the raycaster 2025-07-29 12:12:12 +02:00
26 changed files with 748 additions and 233 deletions

View file

@ -9,7 +9,7 @@ endif
IFLAGS = -I./mlx -I./libft
SOURCEFILES = \
src/consts.c \
src/utils/inits.c \
src/draw/draw_map.c \
src/draw/drawutils.c \
src/main.c \
@ -21,6 +21,11 @@ SOURCEFILES = \
src/utils/hooks.c \
src/map/map_checker.c \
src/player/angle.c \
src/player/player.c \
src/player/move.c \
src/raycast/ray.c \
src/raycast/walls.c \
src/renderer/render.c \
OBJECTS = $(SOURCEFILES:.c=.o)
NAME = cub3d

3
README
View file

@ -13,7 +13,8 @@ z - spawner zombie (porte a six coups pour les zombies)
s - source de son
M - boite magique
faire un systeme de "cheats" soit par un menu de debug soit par une ligne de commande intégrée dans le jeu
faire un systeme de "cheats" soit par un menu de debug soit par une ligne de
commande intégrée dans le jeu
--[ Correspondances des angles / points cardinaux

View file

@ -0,0 +1,35 @@
NO ./path_to_the_north_texture
SO ./path_to_the_south_texture
WE ./path_to_the_west_texture
EA ./path_to_the_east_texture
F 220,100,0
C 225,30,0
1111111111111111111111111111111
1000000000000000000000000000001
1000000000000000000000000000001
1000010000000000000000111110001
1000000000000000000000100010001
1000000000000000000000100010001
1000000000000000000000111110001
1000000000000000000000000000001
1000000000000000000000000000001
1000000000000000000000000000001
1000000000000000000000000000001
1000000000000000000000000000001
1000000000000000000000000000001
1000000000000000000000000000001
1000000000000000000000000000001
1000000000000000000000000000001
1000000000000000000000000000001
1000000000000000000000000000001
1000000000000000000000000000001
10000000000000N0000000000000001
1000000000000000000000000000001
1000000000000000000000000000001
1000000000000000000000000000001
1000000000000000000000000000001
1000000000000000000000000000001
1000000000000000000000000000001
1111111111111111111111111111111

View file

@ -6,7 +6,7 @@
/* By: kcolin <kcolin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/07/17 14:54:36 by kcolin #+# #+# */
/* Updated: 2025/07/29 11:42:20 by kcolin ### ########.fr */
/* Updated: 2025/07/31 11:29:13 by tchampio ### ########.fr */
/* */
/* ************************************************************************** */
@ -18,19 +18,11 @@
# define SIZE 64
# define MAP_SIZE 20
extern const float g_north;
extern const float g_south;
extern const float g_east;
extern const float g_west;
extern const float g_northwest;
extern const float g_northeast;
extern const float g_southwest;
extern const float g_southeast;
# define RESSOURCE_DIR "ressources"
# define MOVEMENT_SPEED 6.4
# define MOVEMENT_SPEED 0.1
# define ROTATION_SPEED 0.1
# define PLANE_VALUE 0.66
# define TEXTURE_SIZE 64
# ifdef BONUS
# define COMPILED_TEXT "Compiled with bonuses"
# else

View file

@ -6,7 +6,7 @@
/* By: kcolin <kcolin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/07/17 14:59:37 by kcolin #+# #+# */
/* Updated: 2025/07/17 15:54:29 by kcolin ### ########.fr */
/* Updated: 2025/07/31 13:23:32 by kcolin ### ########.fr */
/* */
/* ************************************************************************** */
@ -16,14 +16,18 @@
# include "map/mapdata.h"
# include "draw/img_data.h"
# include "player/player.h"
# include "utils/keypresses.h"
# include "consts.h"
typedef struct s_cub3d_data
{
void *mlx;
void *mlx_win;
t_img_data *img_data;
t_mapdata *map;
t_player player;
void *mlx;
void *mlx_win;
t_img_data *img_data;
t_mapdata *map;
t_player player;
t_keypresses keypresses;
int *screen_matrix;
} t_cub3d_data;
#endif // CUB3D_DATA_H

View file

@ -6,7 +6,7 @@
/* By: kcolin <kcolin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/07/17 14:20:00 by kcolin #+# #+# */
/* Updated: 2025/07/29 11:58:34 by kcolin ### ########.fr */
/* Updated: 2025/07/29 14:16:07 by tchampio ### ########.fr */
/* */
/* ************************************************************************** */
@ -59,5 +59,5 @@ void draw_map(t_mapdata *map, t_player *player, t_img_data *data)
}
i++;
}
draw_2d_wall(0x00FF0000, data, MAP_SIZE * ((player->x - (float)SIZE / 2)) / SIZE, MAP_SIZE * ((player->y - (float)SIZE / 2) / SIZE));
draw_2d_wall(0x00FF0000, data, MAP_SIZE * player->x, MAP_SIZE * player->y);
}

View file

@ -6,7 +6,7 @@
/* By: kcolin <kcolin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/07/17 14:14:30 by kcolin #+# #+# */
/* Updated: 2025/07/29 11:56:42 by kcolin ### ########.fr */
/* Updated: 2025/07/31 13:30:05 by tchampio ### ########.fr */
/* */
/* ************************************************************************** */
@ -14,145 +14,29 @@
#include "../mlx/mlx.h"
#include "consts.h"
#include "cub3d_data.h"
#include "draw/drawutils.h"
#include "map/map_checker.h"
#include "player/move.h"
#include "draw/draw_map.h"
#include "map/mapdata.h"
#include "player/player.h"
#include "raycast/raycaster.h"
#include "renderer/render.h"
#include "raycast/ray.h"
#include "utils/hooks.h"
#include "utils/frees.h"
#include "utils/inits.h"
#include <stdbool.h>
#include <X11/keysym.h>
#include <X11/X.h>
#include <unistd.h>
#include <fcntl.h>
#include <math.h>
#include <stdio.h> // BAD
void init_player(t_mapdata *mapdata, t_player *player)
{
player->health = 100;
player->x = mapdata->startx * SIZE + ((float)SIZE / 2);
player->y = mapdata->starty * SIZE + ((float)SIZE / 2);
if (mapdata->map[mapdata->starty][mapdata->startx] == 'N')
player->yaw = M_PI;
else if (mapdata->map[mapdata->starty][mapdata->startx] == 'S')
player->yaw = 0;
else if (mapdata->map[mapdata->starty][mapdata->startx] == 'E')
player->yaw = M_PI / 2;
else if (mapdata->map[mapdata->starty][mapdata->startx] == 'W')
player->yaw = 3 * M_PI / 2;
}
bool touch(float px, float py, t_mapdata *map)
{
int x;
int y;
x = px / SIZE;
y = py / SIZE;
if (map->map[y][x] == '1')
return (true);
return (false);
}
void draw_line(t_cub3d_data *data, float start_angle)
{
float cos_angle = cos(start_angle);
float sin_angle = sin(start_angle);
float ray_x = data->player.x;
float ray_y = data->player.y;
while(!touch(ray_x, ray_y, data->map))
{
my_mlx_pixel_put(data->img_data, (int)(MAP_SIZE * (ray_x / SIZE)), (int)(MAP_SIZE * (ray_y / SIZE)), 0xcc241b);
ray_x += sin_angle;
ray_y += cos_angle;
}
}
t_cardinal_dir angle_cardinal_dir(float angle)
{
if (angle >= g_southwest || (angle > g_south && angle < g_southeast))
return (SOUTH);
if (angle >= g_southeast && angle < g_northeast)
return (EAST);
if (angle >= g_northeast && angle < g_northwest)
return (NORTH);
return (WEST);
}
t_cardinal_dir player_cardinal_dir(t_player player)
{
return (angle_cardinal_dir(player.yaw));
}
t_intercardinal_dir angle_intercardinal_dir(float angle)
{
if (angle >= g_south && angle < g_east)
return (SOUTHEAST);
if (angle >= g_east && angle < g_north)
return (NORTHEAST);
if (angle >= g_north && angle < g_west)
return (NORTHWEST);
return (SOUTHWEST);
}
t_intercardinal_dir player_intercardinal_dir(t_player player)
{
return (angle_intercardinal_dir(player.yaw));
}
/*
** Converts a coordinate from global map space to local tile space.
**
** input coordinate is in the full map
** output coordinate is in the current tile
*/
float coord_global_to_local(float coord)
{
return (coord - floor(coord / SIZE) * SIZE);
}
int game_loop(t_cub3d_data *data)
{
t_ray ray;
mlx_destroy_image(data->mlx, data->img_data->img);
data->img_data->img = mlx_new_image(data->mlx, WIDTH, HEIGHT);
if (player_intercardinal_dir(data->player) == SOUTHEAST)
ft_printf("southeast ");
if (player_intercardinal_dir(data->player) == SOUTHWEST)
ft_printf("southwest ");
if (player_intercardinal_dir(data->player) == NORTHEAST)
ft_printf("northeast ");
if (player_intercardinal_dir(data->player) == NORTHWEST)
ft_printf("northwest ");
if (player_cardinal_dir(data->player) == SOUTH)
ft_printf("south\n");
if (player_cardinal_dir(data->player) == EAST)
ft_printf("east\n");
if (player_cardinal_dir(data->player) == NORTH)
ft_printf("north\n");
if (player_cardinal_dir(data->player) == WEST)
ft_printf("west\n");
printf("local coord: %f, %f\n", coord_global_to_local(data->player.x), coord_global_to_local(data->player.y));
/* float ray_angle = data->player.yaw - M_PI / 6; // 30 deg clockwise from player */
float ray_angle = data->player.yaw; // straight ahead
float fraction = M_PI / 3 / WIDTH;
int column = 0;
while (column < 1)
{
float first_hline_distance = coord_global_to_local(data->player.y) / cos(ray_angle);
printf("first hline distance: %f\n", first_hline_distance);
draw_line(data, ray_angle);
column++;
ray_angle += fraction;
}
reset_matrix(data);
raycaster(data, &ray);
move_player(data);
matrix_to_image(data);
draw_map(data->map, &data->player, data->img_data);
mlx_put_image_to_window(data->mlx, data->mlx_win,
data->img_data->img, 0, 0);
@ -166,21 +50,7 @@ int main(int argc, char **argv)
if (argc < 2)
return (ft_printf("Error: Missing cub3d file\n"), 1);
data.map = ft_calloc(sizeof(t_mapdata), 1);
if (!check_cubfile(argv[1], data.map))
return (ft_printf("Error: Wrong map file. Reason: %s\n",
data.map->error), free_map(data.map), 1);
data.mlx = mlx_init();
if (data.mlx == NULL)
return (ft_printf("Error: Failed to initalize mlx\n"),
free_map(data.map), 1);
data.mlx_win = mlx_new_window(data.mlx, WIDTH, HEIGHT, "Cub3d");
data.img_data = ft_calloc(sizeof(t_img_data), 1);
data.img_data->img = mlx_new_image(data.mlx, WIDTH, HEIGHT);
data.img_data->addr = mlx_get_data_addr(data.img_data->img,
&data.img_data->bits_per_pixel, &data.img_data->line_length,
&data.img_data->endian);
init_player(data.map, &(data.player));
init_cub3d_data(&data, argv);
mlx_hook(data.mlx_win, KeyPress, KeyPressMask, keypress_handler, &data);
mlx_hook(data.mlx_win, KeyRelease, KeyReleaseMask,
keyrelease_handler, &data);

View file

@ -6,7 +6,7 @@
/* By: kcolin <kcolin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/06/06 17:54:42 by tchampio #+# #+# */
/* Updated: 2025/07/23 13:33:05 by kcolin ### ########.fr */
/* Updated: 2025/07/29 14:43:32 by tchampio ### ########.fr */
/* */
/* ************************************************************************** */

View file

@ -6,42 +6,50 @@
/* By: tchampio <tchampio@student.42lehavre. +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/07/24 14:41:35 by tchampio #+# #+# */
/* Updated: 2025/07/24 14:48:04 by tchampio ### ########.fr */
/* Updated: 2025/07/29 20:09:55 by tchampio ### ########.fr */
/* */
/* ************************************************************************** */
#include <X11/keysym.h>
#include <X11/X.h>
#include "../cub3d_data.h"
#include "../consts.h"
#include <math.h>
#include <X11/keysym.h>
#include <X11/X.h>
#include "player.h"
/* key parameter should be X's value such as XK_a */
void apply_angle(int key, t_cub3d_data *data)
void turn_right_angle(t_cub3d_data *data)
{
double cos_angle;
double sin_angle;
t_player *p;
double prev_dir_x;
double prev_plane_x;
cos_angle = cos(data->player.yaw);
sin_angle = sin(data->player.yaw);
if (key == XK_a)
{
data->player.x += cos_angle * MOVEMENT_SPEED;
data->player.y -= sin_angle * MOVEMENT_SPEED;
}
if (key == XK_d)
{
data->player.x -= cos_angle * MOVEMENT_SPEED;
data->player.y += sin_angle * MOVEMENT_SPEED;
}
if (key == XK_w)
{
data->player.x += sin_angle * MOVEMENT_SPEED;
data->player.y += cos_angle * MOVEMENT_SPEED;
}
if (key == XK_s)
{
data->player.x -= sin_angle * MOVEMENT_SPEED;
data->player.y -= cos_angle * MOVEMENT_SPEED;
}
p = &data->player;
prev_dir_x = p->dir_x;
prev_plane_x = p->plane_x;
p->dir_x = p->dir_x * cos(ROTATION_SPEED) - p->dir_y * sin(ROTATION_SPEED);
p->dir_y = prev_dir_x * sin(ROTATION_SPEED)
+ p->dir_y * cos(ROTATION_SPEED);
p->plane_x = p->plane_x * cos(ROTATION_SPEED)
- p->plane_y * sin(ROTATION_SPEED);
p->plane_y = prev_plane_x * sin(ROTATION_SPEED)
+ p->plane_y * cos(ROTATION_SPEED);
}
void turn_left_angle(t_cub3d_data *data)
{
t_player *p;
double prev_dir_x;
double prev_plane_x;
p = &data->player;
prev_dir_x = p->dir_x;
prev_plane_x = p->plane_x;
p->dir_x = p->dir_x * cos(-ROTATION_SPEED)
- p->dir_y * sin(-ROTATION_SPEED);
p->dir_y = prev_dir_x * sin(-ROTATION_SPEED)
+ p->dir_y * cos(-ROTATION_SPEED);
p->plane_x = p->plane_x * cos(-ROTATION_SPEED)
- p->plane_y * sin(-ROTATION_SPEED);
p->plane_y = prev_plane_x * sin(-ROTATION_SPEED)
+ p->plane_y * cos(-ROTATION_SPEED);
}

View file

@ -6,7 +6,7 @@
/* By: tchampio <tchampio@student.42lehavre. +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/07/24 14:46:11 by tchampio #+# #+# */
/* Updated: 2025/07/24 14:48:52 by tchampio ### ########.fr */
/* Updated: 2025/07/29 19:34:34 by tchampio ### ########.fr */
/* */
/* ************************************************************************** */
@ -16,6 +16,7 @@
# include "../cub3d_data.h"
# include "../consts.h"
void apply_angle(int key, t_cub3d_data *data);
void turn_left_angle(t_cub3d_data *data);
void turn_right_angle(t_cub3d_data *data);
#endif // ANGLE_H

91
src/player/move.c Normal file
View file

@ -0,0 +1,91 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* move.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: tchampio <tchampio@student.42lehavre. +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/07/29 13:58:00 by tchampio #+# #+# */
/* Updated: 2025/07/29 19:47:38 by tchampio ### ########.fr */
/* */
/* ************************************************************************** */
#include "../cub3d_data.h"
#include "angle.h"
#include "../consts.h"
void move_player_forward(t_cub3d_data *data)
{
char **map;
double next_x;
double next_y;
map = data->map->map;
next_x = data->player.x + data->player.dir_x * MOVEMENT_SPEED;
next_y = data->player.y + data->player.dir_y * MOVEMENT_SPEED;
if (map[(int)data->player.y][(int)next_x] == '0')
data->player.x += data->player.dir_x * MOVEMENT_SPEED;
if (map[(int)next_y][(int)data->player.x] == '0')
data->player.y += data->player.dir_y * MOVEMENT_SPEED;
}
void move_player_backward(t_cub3d_data *data)
{
char **map;
double next_x;
double next_y;
map = data->map->map;
next_x = data->player.x - data->player.dir_x * MOVEMENT_SPEED;
next_y = data->player.y - data->player.dir_y * MOVEMENT_SPEED;
if (map[(int)data->player.y][(int)next_x] == '0')
data->player.x -= data->player.dir_x * MOVEMENT_SPEED;
if (map[(int)next_y][(int)data->player.x] == '0')
data->player.y -= data->player.dir_y * MOVEMENT_SPEED;
}
void move_player_strafe_left(t_cub3d_data *data)
{
char **map;
double next_x;
double next_y;
map = data->map->map;
next_x = data->player.x - data->player.plane_x * MOVEMENT_SPEED;
next_y = data->player.y - data->player.plane_y * MOVEMENT_SPEED;
if (map[(int)data->player.y][(int)next_x] == '0')
data->player.x -= data->player.plane_x * MOVEMENT_SPEED;
if (map[(int)next_y][(int)data->player.x] == '0')
data->player.y -= data->player.plane_y * MOVEMENT_SPEED;
}
void move_player_strafe_right(t_cub3d_data *data)
{
char **map;
double next_x;
double next_y;
map = data->map->map;
next_x = data->player.x + data->player.plane_x * MOVEMENT_SPEED;
next_y = data->player.y + data->player.plane_y * MOVEMENT_SPEED;
if (map[(int)data->player.y][(int)next_x] == '0')
data->player.x += data->player.plane_x * MOVEMENT_SPEED;
if (map[(int)next_y][(int)data->player.x] == '0')
data->player.y += data->player.plane_y * MOVEMENT_SPEED;
}
void move_player(t_cub3d_data *data)
{
if (data->keypresses.is_w_pressed)
move_player_forward(data);
if (data->keypresses.is_s_pressed)
move_player_backward(data);
if (data->keypresses.is_a_pressed)
move_player_strafe_left(data);
if (data->keypresses.is_d_pressed)
move_player_strafe_right(data);
if (data->keypresses.is_left_pressed)
turn_left_angle(data);
if (data->keypresses.is_right_pressed)
turn_right_angle(data);
}

20
src/player/move.h Normal file
View file

@ -0,0 +1,20 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* move.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: tchampio <tchampio@student.42lehavre. +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/07/29 13:58:49 by tchampio #+# #+# */
/* Updated: 2025/07/29 20:13:08 by tchampio ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef MOVE_H
# define MOVE_H
# include "../cub3d_data.h"
void move_player(t_cub3d_data *data);
#endif

69
src/player/player.c Normal file
View file

@ -0,0 +1,69 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* player.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: tchampio <tchampio@student.42lehavre. +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/07/29 11:42:44 by tchampio #+# #+# */
/* Updated: 2025/07/29 20:13:01 by tchampio ### ########.fr */
/* */
/* ************************************************************************** */
#include "player.h"
#include "../map/mapdata.h"
#include "../consts.h"
// east west
void init_lon(t_player *player, char dir)
{
if (dir == 'N')
{
player->dir_x = 0;
player->dir_y = -1;
player->plane_x = PLANE_VALUE;
player->plane_y = 0;
}
else
{
player->dir_x = 0;
player->dir_y = 1;
player->plane_x = -PLANE_VALUE;
player->plane_y = 0;
}
}
// north south
void init_lat(t_player *player, char dir)
{
if (dir == 'E')
{
player->dir_x = 1;
player->dir_y = 0;
player->plane_x = 0;
player->plane_y = PLANE_VALUE;
}
else
{
player->dir_x = -1;
player->dir_y = 0;
player->plane_x = 0;
player->plane_y = -PLANE_VALUE;
}
}
void init_player(t_player *player, t_mapdata *map)
{
char dir;
dir = map->map[map->starty][map->startx];
player->x = map->startx + 0.5;
player->y = map->starty + 0.5;
map->map[map->starty][map->startx] = '0';
player->health = 100;
player->points = 500;
if (dir == 'N' || dir == 'S')
init_lon(player, dir);
else
init_lat(player, dir);
}

View file

@ -6,13 +6,15 @@
/* By: kcolin <kcolin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/07/17 15:51:29 by kcolin #+# #+# */
/* Updated: 2025/07/24 14:07:09 by tchampio ### ########.fr */
/* Updated: 2025/07/29 13:28:08 by tchampio ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef PLAYER_H
# define PLAYER_H
# include "../map/mapdata.h"
typedef struct s_vec2
{
double x;
@ -23,9 +25,15 @@ typedef struct s_player
{
double x;
double y;
double yaw;
double dir_x;
double dir_y;
double plane_x;
double plane_y;
int health;
int points;
t_vec2 movement;
} t_player;
void init_player(t_player *player, t_mapdata *map);
#endif // PLAYER_H

113
src/raycast/ray.c Normal file
View file

@ -0,0 +1,113 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ray.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: kcolin <kcolin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/07/31 11:55:41 by kcolin #+# #+# */
/* Updated: 2025/07/31 11:58:02 by kcolin ### ########.fr */
/* */
/* ************************************************************************** */
#include "ray.h"
#include "raycaster.h"
#include "../player/player.h"
#include "../consts.h"
#include "../cub3d_data.h"
#include <float.h>
#include <math.h>
void init_ray(t_ray *ray, int pos_x, t_player *player)
{
ray->plane = 2 * pos_x / (double)WIDTH - 1;
ray->dir_x = player->dir_x + player->plane_x * ray->plane;
ray->dir_y = player->dir_y + player->plane_y * ray->plane;
ray->map_x = (int)player->x;
ray->map_y = (int)player->y;
ray->delta_dist_x = fabs(1 / ray->dir_x);
ray->delta_dist_y = fabs(1 / ray->dir_y);
}
void ray_calculate_step(t_ray *ray, t_player *player)
{
if (ray->dir_x < 0)
{
ray->step_x = -1;
ray->side_dist_x = (player->x - ray->map_x) * ray->delta_dist_x;
}
else
{
ray->step_x = 1;
ray->side_dist_x = (ray->map_x + 1.0 - player->x) * ray->delta_dist_x;
}
if (ray->dir_y < 0)
{
ray->step_y = -1;
ray->side_dist_y = (player->y - ray->map_y) * ray->delta_dist_y;
}
else
{
ray->step_y = 1;
ray->side_dist_y = (ray->map_y + 1.0 - player->y) * ray->delta_dist_y;
}
}
void calculate_wall_dist(t_ray *ray, char **map)
{
while (true)
{
if (ray->side_dist_x < ray->side_dist_y)
{
ray->side_dist_x += ray->delta_dist_x;
ray->map_x += ray->step_x;
ray->side = 0;
}
else
{
ray->side_dist_y += ray->delta_dist_y;
ray->map_y += ray->step_y;
ray->side = 1;
}
if (map[ray->map_y][ray->map_x] != '0')
break ;
}
if (ray->side == 0)
ray->wall_dist = ray->side_dist_x - ray->delta_dist_x;
else
ray->wall_dist = ray->side_dist_y - ray->delta_dist_y;
}
void calculate_wall_height(t_ray *ray, t_player *player)
{
if (ray->wall_dist <= FLT_EPSILON)
ray->wall_dist = 0.1;
ray->wall_height = (int)(HEIGHT / ray->wall_dist);
ray->draw_start = -ray->wall_height / 2 + HEIGHT / 2;
if (ray->draw_start < 0)
ray->draw_start = 0;
ray->draw_end = ray->wall_height / 2 + HEIGHT / 2;
if (ray->draw_end >= HEIGHT)
ray->draw_end = HEIGHT - 1;
if (ray->side == 0)
ray->wall_x = player->y + ray->wall_dist * ray->dir_y;
else
ray->wall_x = player->x + ray->wall_dist * ray->dir_x;
ray->wall_x -= floor(ray->wall_x);
}
void raycaster(t_cub3d_data *data, t_ray *ray)
{
int x;
x = 0;
while (x < WIDTH)
{
init_ray(ray, x, &data->player);
ray_calculate_step(ray, &data->player);
calculate_wall_dist(ray, data->map->map);
calculate_wall_height(ray, &data->player);
render_walls(data, ray, x);
x++;
}
}

53
src/raycast/ray.h Normal file
View file

@ -0,0 +1,53 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ray.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: tchampio <tchampio@student.42lehavre. +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/07/29 11:32:20 by tchampio #+# #+# */
/* Updated: 2025/07/30 16:46:05 by tchampio ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef RAY_H
# define RAY_H
/*
* plane - plan de camera (vectoriel)
* dir_x - Direction (pour X)
* dir_y - Direction (pour Y)
* map_x - Position dans la map du rayon
* map_y - Position dans la map du rayon
* step_x - "pas" d'un rayon
* step_y
* side_dist_x - Distance horizontale avant la prochaine section de quadrillage
* side_dist_y - idem mais pour le vertical
* wall_dist - distance du mur touché
* side - de quel cote part le rayon
* wall_height - Hauteur du mur a dessiner
* draw_start - x boucle de la matrice de pixel pour dessiner a la bonne hauteur
* draw_end - fin du dessin du mur
*/
typedef struct s_ray
{
double plane;
double dir_x;
double dir_y;
int map_x;
int map_y;
int step_x;
int step_y;
double side_dist_x;
double side_dist_y;
double delta_dist_x;
double delta_dist_y;
double wall_dist;
int side;
int wall_height;
int draw_start;
int draw_end;
double wall_x;
} t_ray;
#endif // RAY_H

22
src/raycast/raycaster.h Normal file
View file

@ -0,0 +1,22 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* raycaster.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: tchampio <tchampio@student.42lehavre.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/07/30 15:16:04 by tchampio #+# #+# */
/* Updated: 2025/07/30 15:17:02 by tchampio ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef RAYCASTER_H
# define RAYCASTER_H
# include "ray.h"
# include "../cub3d_data.h"
void raycaster(t_cub3d_data *data, t_ray *ray);
void render_walls(t_cub3d_data *data, t_ray *ray, int x);
#endif // RAYCASTER_H

83
src/raycast/walls.c Normal file
View file

@ -0,0 +1,83 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* render.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: kcolin <kcolin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/07/31 13:17:39 by kcolin #+# #+# */
/* Updated: 2025/07/31 13:38:07 by kcolin ### ########.fr */
/* */
/* ************************************************************************** */
#include "../cub3d_data.h"
#include "../consts.h"
#include "ray.h"
#include "../renderer/render.h"
int get_cardinal(t_ray *ray)
{
if (ray->side == 0)
{
if (ray->dir_x < 0)
return (2);
else
return (3);
}
else
{
if (ray->dir_y > 0)
return (1);
else
return (0);
}
}
static int get_color(int dir)
{
int color;
if (dir == 0)
color = 0x0000ff;
else if (dir == 1)
color = 0x00ff00;
else if (dir == 2)
color = 0xff0000;
else if (dir == 3)
color = 0xffeb3b;
else
color = 0xff53ff;
return (color);
}
/*
* Dir values are:
* 0: North
* 1: South
* 2: West
* 3: East
*/
void render_walls(t_cub3d_data *data, t_ray *ray, int x)
{
int dir;
int tex_x;
unsigned int color;
double step;
double pos;
dir = get_cardinal(ray);
tex_x = (int)(ray->wall_x * TEXTURE_SIZE);
if ((ray->side == 0 && ray->dir_x < 0)
|| (ray->side == 1 && ray->dir_y > 0))
tex_x = TEXTURE_SIZE - tex_x - 1;
step = 1.0 * TEXTURE_SIZE / ray->wall_height;
pos = (ray->draw_start - HEIGHT / 2 + ray->wall_height / 2) * step;
while (ray->draw_start < ray->draw_end)
{
pos += step;
color = get_color(dir);
(void)pos;
matrix_set(data, x, ray->draw_start, color);
ray->draw_start++;
}
}

52
src/renderer/render.c Normal file
View file

@ -0,0 +1,52 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* render.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: kcolin <kcolin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/07/31 13:18:17 by kcolin #+# #+# */
/* Updated: 2025/07/31 13:38:49 by kcolin ### ########.fr */
/* */
/* ************************************************************************** */
#include "render.h"
#include "../consts.h"
#include "../cub3d_data.h"
#include "../draw/drawutils.h"
#include "../../libft/includes/libft.h"
void reset_matrix(t_cub3d_data *data)
{
ft_bzero(data->screen_matrix, sizeof(int) * WIDTH * HEIGHT);
}
int matrix_get(t_cub3d_data *data, int x, int y)
{
return (data->screen_matrix[y + x * WIDTH]);
}
void matrix_set(t_cub3d_data *data, int x, int y, int color)
{
data->screen_matrix[y + x * WIDTH] = color;
}
void matrix_to_image(t_cub3d_data *data)
{
int x;
int y;
y = 0;
while (y < HEIGHT)
{
x = 0;
while (x < WIDTH)
{
if (matrix_get(data, x, y) > 0)
my_mlx_pixel_put(data->img_data,
x, y, matrix_get(data, x, y));
x++;
}
y++;
}
}

View file

@ -1,23 +1,22 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* consts.c :+: :+: :+: */
/* render.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: kcolin <kcolin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/07/28 14:33:12 by kcolin #+# #+# */
/* Updated: 2025/07/28 15:03:16 by kcolin ### ########.fr */
/* Created: 2025/07/31 13:36:36 by kcolin #+# #+# */
/* Updated: 2025/07/31 13:36:43 by kcolin ### ########.fr */
/* */
/* ************************************************************************** */
#include "consts.h"
#include <math.h>
#ifndef RENDER_H
# define RENDER_H
const float g_north = M_PI;
const float g_south = 0;
const float g_east = M_PI / 2;
const float g_west = 3 * M_PI / 2;
const float g_northwest = 5 * M_PI / 4;
const float g_northeast = 3 * M_PI / 4;
const float g_southwest = 7 * M_PI / 4;
const float g_southeast = M_PI / 4;
# include "../cub3d_data.h"
void reset_matrix(t_cub3d_data *data);
void matrix_to_image(t_cub3d_data *data);
void matrix_set(t_cub3d_data *data, int x, int y, int color);
#endif // RENDER_H

View file

@ -6,7 +6,7 @@
/* By: kcolin <kcolin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/07/17 13:59:27 by kcolin #+# #+# */
/* Updated: 2025/07/23 12:18:08 by tchampio ### ########.fr */
/* Updated: 2025/07/31 13:26:06 by kcolin ### ########.fr */
/* */
/* ************************************************************************** */
@ -69,6 +69,7 @@ int destroy(t_cub3d_data *data)
if (data->mlx)
mlx_destroy_display(data->mlx);
free(data->mlx);
free(data->screen_matrix);
exit(0);
return (0);
}

View file

@ -6,11 +6,12 @@
/* By: kcolin <kcolin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/07/17 14:22:57 by kcolin #+# #+# */
/* Updated: 2025/07/25 14:55:54 by tchampio ### ########.fr */
/* Updated: 2025/07/29 13:35:29 by tchampio ### ########.fr */
/* */
/* ************************************************************************** */
#include "../consts.h"
#include "../cub3d_data.h"
#include "../player/angle.h"
#include "frees.h"
#include <X11/keysym.h>
@ -22,31 +23,34 @@ int keypress_handler(int keycode, t_cub3d_data *data)
{
if (keycode == XK_Escape)
destroy(data);
if (keycode == XK_w)
data->keypresses.is_w_pressed = true;
if (keycode == XK_a)
data->keypresses.is_a_pressed = true;
if (keycode == XK_s)
data->keypresses.is_s_pressed = true;
if (keycode == XK_d)
data->keypresses.is_d_pressed = true;
if (keycode == XK_Left)
data->player.yaw += ROTATION_SPEED;
else if (keycode == XK_Right)
data->player.yaw -= ROTATION_SPEED;
if (data->player.yaw > 2 * M_PI)
data->player.yaw -= 2 * M_PI;
if (data->player.yaw < 0)
data->player.yaw += 2 * M_PI;
if (keycode == XK_a || keycode == XK_d
|| keycode == XK_w || keycode == XK_s)
apply_angle(keycode, data);
data->keypresses.is_left_pressed = true;
if (keycode == XK_Right)
data->keypresses.is_right_pressed = true;
return (0);
}
int keyrelease_handler(int keycode, t_cub3d_data *data)
{
if (keycode == XK_Escape)
destroy(data);
if (keycode == XK_a)
data->player.movement.x = 0;
if (keycode == XK_d)
data->player.movement.x = 0;
if (keycode == XK_w)
data->player.movement.y = 0;
data->keypresses.is_w_pressed = false;
if (keycode == XK_a)
data->keypresses.is_a_pressed = false;
if (keycode == XK_s)
data->player.movement.y = 0;
data->keypresses.is_s_pressed = false;
if (keycode == XK_d)
data->keypresses.is_d_pressed = false;
if (keycode == XK_Left)
data->keypresses.is_left_pressed = false;
if (keycode == XK_Right)
data->keypresses.is_right_pressed = false;
return (0);
}

View file

@ -6,7 +6,7 @@
/* By: kcolin <kcolin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/07/17 14:23:06 by kcolin #+# #+# */
/* Updated: 2025/07/17 15:50:08 by kcolin ### ########.fr */
/* Updated: 2025/07/29 13:42:22 by tchampio ### ########.fr */
/* */
/* ************************************************************************** */

38
src/utils/inits.c Normal file
View file

@ -0,0 +1,38 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* inits.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: tchampio <tchampio@student.42lehavre. +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/07/31 13:26:53 by tchampio #+# #+# */
/* Updated: 2025/07/31 13:28:03 by tchampio ### ########.fr */
/* */
/* ************************************************************************** */
#include "../cub3d_data.h"
#include "../../libft/includes/libft.h"
#include "../../mlx/mlx.h"
#include "../map/map_checker.h"
#include "frees.h"
void init_cub3d_data(t_cub3d_data *data, char **argv)
{
ft_bzero(data, sizeof(*data));
data->map = ft_calloc(sizeof(t_mapdata), 1);
if (!check_cubfile(argv[1], data->map))
return (ft_printf("Error: Wrong map file. Reason: %s\n",
data->map->error), free_map(data->map), exit(1));
data->mlx = mlx_init();
if (data->mlx == NULL)
return (ft_printf("Error: Failed to initalize mlx\n"),
free_map(data->map), exit(1));
data->mlx_win = mlx_new_window(data->mlx, WIDTH, HEIGHT, "Cub3d");
data->img_data = ft_calloc(sizeof(t_img_data), 1);
data->img_data->img = mlx_new_image(data->mlx, WIDTH, HEIGHT);
data->img_data->addr = mlx_get_data_addr(data->img_data->img,
&data->img_data->bits_per_pixel, &data->img_data->line_length,
&data->img_data->endian);
init_player(&data->player, data->map);
data->screen_matrix = ft_calloc(sizeof(int), WIDTH * HEIGHT);
}

20
src/utils/inits.h Normal file
View file

@ -0,0 +1,20 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* inits.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: tchampio <tchampio@student.42lehavre. +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/07/31 13:28:47 by tchampio #+# #+# */
/* Updated: 2025/07/31 13:29:35 by tchampio ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef INITS_H
# define INITS_H
# include "../cub3d_data.h"
void init_cub3d_data(t_cub3d_data *data, char **argv);
#endif // INITS_H

26
src/utils/keypresses.h Normal file
View file

@ -0,0 +1,26 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* keypresses.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: tchampio <tchampio@student.42lehavre. +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/07/29 13:42:39 by tchampio #+# #+# */
/* Updated: 2025/07/29 20:09:30 by tchampio ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef KEYPRESSES_H
# define KEYPRESSES_H
typedef struct s_keypresses
{
bool is_w_pressed;
bool is_a_pressed;
bool is_s_pressed;
bool is_d_pressed;
bool is_left_pressed;
bool is_right_pressed;
} t_keypresses;
#endif // KEYPRESSES_H