From 50b45e597fa7a7a94de8eb97543ea31e272bc886 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 15 Nov 2025 22:16:13 +0000 Subject: [PATCH] intra to gitea --- .gitignore | 2 + .vscode/settings.json | 21 +++ Makefile | 4 +- gnl/srcs/get_next_line.c | 32 ++-- includes/cub.h | 9 +- includes/exec.h | 124 +++++++++++---- maps/good/library.cub | 4 +- maps/good/test.cub | 2 +- srcs/exec/draw.c | 67 +++++--- srcs/exec/hooks.c | 29 ++-- srcs/exec/init.c | 2 +- srcs/exec/loop.c | 3 - srcs/exec/player.c | 105 ++++++------- srcs/exec/raycast.c | 303 ++++++++++-------------------------- srcs/exec/raycast_utils.c | 97 ++++++++++++ srcs/exec/textures.c | 21 ++- srcs/exec/world.c | 99 ++++++------ srcs/main.c | 191 ++--------------------- srcs/main.c_old | 218 ++++++++++++++++++++++++++ srcs/parsing/check_file.c | 2 + srcs/parsing/get_map.c | 6 +- srcs/parsing/get_map_2.c | 2 + srcs/parsing/get_textures.c | 21 ++- srcs/parsing/line_detect.c | 6 +- srcs/utils/free.c | 33 ++++ srcs/utils/init.c | 82 +++++++++- srcs/utils/utils.c | 29 ++-- 27 files changed, 889 insertions(+), 625 deletions(-) create mode 100644 .gitignore create mode 100644 .vscode/settings.json create mode 100644 srcs/exec/raycast_utils.c create mode 100644 srcs/main.c_old create mode 100644 srcs/utils/free.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..151a620 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.o +*.a \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..035e19c --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,21 @@ +{ + "files.associations": { + "bit": "c", + "climits": "c", + "cmath": "c", + "compare": "c", + "concepts": "c", + "cstdarg": "c", + "cstdint": "c", + "cstdio": "c", + "cstdlib": "c", + "type_traits": "c", + "utility": "c", + "initializer_list": "c", + "limits": "c", + "new": "c", + "cstdbool": "c", + "typeinfo": "c", + "*.inc": "c" + } +} \ No newline at end of file diff --git a/Makefile b/Makefile index ba486ea..8188f9a 100644 --- a/Makefile +++ b/Makefile @@ -38,6 +38,7 @@ SRCS = \ $(SRCDIR)/parsing/check_map_2.c \ $(SRCDIR)/utils/init.c \ $(SRCDIR)/utils/utils.c \ + $(SRCDIR)/utils/free.c \ $(SRCDIR)/exec/draw.c \ $(SRCDIR)/exec/hooks.c \ $(SRCDIR)/exec/image.c \ @@ -46,7 +47,8 @@ SRCS = \ $(SRCDIR)/exec/player.c \ $(SRCDIR)/exec/raycast.c \ $(SRCDIR)/exec/textures.c \ - $(SRCDIR)/exec/world.c + $(SRCDIR)/exec/world.c \ + $(SRCDIR)/exec/raycast_utils.c # === Includes === INCS = \ diff --git a/gnl/srcs/get_next_line.c b/gnl/srcs/get_next_line.c index 936a614..94167e1 100644 --- a/gnl/srcs/get_next_line.c +++ b/gnl/srcs/get_next_line.c @@ -62,20 +62,30 @@ static char *extract(char *line) return (backup); } +static char *process_line(char *line, char **backup) +{ + char *temp; + + *backup = extract(line); + temp = ft_strdup_g(line); + free(line); + if (!temp) + { + free(*backup); + *backup = NULL; + return (NULL); + } + return (temp); +} + char *get_next_line(int fd) { char *line; char *buf; - char *temp; static char *backup; if (fd == -2) - { - if (backup) - free(backup); - backup = NULL; - return (NULL); - } + return (free(backup), backup = NULL, NULL); if (fd < 0 || BUFFER_SIZE <= 0) return (free(backup), backup = NULL, NULL); buf = (char *)malloc(sizeof(char) * (BUFFER_SIZE + 1)); @@ -83,15 +93,9 @@ char *get_next_line(int fd) return (free(backup), backup = NULL, NULL); line = sort_and_store(fd, buf, backup); free(buf); - buf = NULL; if (!line) return (free(backup), backup = NULL, NULL); - backup = extract(line); - temp = ft_strdup_g(line); - free(line); - if (!temp) - return (free(backup), backup = NULL, NULL); - return (temp); + return (process_line(line, &backup)); } // int main() diff --git a/includes/cub.h b/includes/cub.h index 7b0dc00..c333b87 100644 --- a/includes/cub.h +++ b/includes/cub.h @@ -52,13 +52,20 @@ typedef struct s_data //utils void ft_error(char *message); -void free_char_array(char **array); +int rgb_to_int(int r, int g, int b); int ft_arrlen(char **arr); void print_array(char **array); int ft_strlen_2d(char **str); //init int init_data(t_data *data, char *path); +int world_init_from_parsing(t_world *world, t_data *data); +int init_game_data(t_game *g, t_data *data, char *map_file); +void init_player_direction(t_player_init *p, char direction); +int init_mlx_and_textures(t_game *g, t_data *data); + +//free.c void free_data(t_data *data); +void free_char_array(char **array); #endif diff --git a/includes/exec.h b/includes/exec.h index f160cd2..f25e525 100644 --- a/includes/exec.h +++ b/includes/exec.h @@ -45,7 +45,7 @@ typedef struct s_colors { int floor; int ceil; - int wall_nsew[4]; /* 0:N 1:S 2:E 3:W → couleurs simples pour l’instant */ + int wall_nsew[4]; } t_colors; /* Entrées clavier (état des touches) */ @@ -64,7 +64,7 @@ typedef struct s_world { int w; int h; - char **grid; /* '0' vide, '1' mur */ + char **grid; } t_world; /* Caméra / joueur (Raycasting) */ @@ -102,56 +102,116 @@ typedef struct s_game double move_speed; double rot_speed; - /* --- Textures --- */ - t_tex tex[4]; /* 0:N 1:S 2:E 3:W */ - int has_tex; /* 1 si chargées OK */ - - /* Pour le cleanup */ - t_data *data; /* pointeur vers data pour cleanup */ + t_tex tex[4]; + int has_tex; + + t_data *data; } t_game; +typedef struct s_texpaths +{ + const char *no; + const char *so; + const char *we; + const char *ea; +} t_texpaths; + +typedef struct s_player_init +{ + double px; + double py; + double dx; + double dy; +} t_player_init; + +typedef struct s_texline +{ + t_tex *tex; + int tex_x; + double step; + double tex_pos; + int y0; + int y1; +} t_texline; + +typedef struct s_vline +{ + int y0; + int y1; + int color; +} t_vline; + +typedef struct s_ray +{ + double ray_dir_x; + double ray_dir_y; + int map_x; + int map_y; + double delta_dist_x; + double delta_dist_y; + double side_dist_x; + double side_dist_y; + int step_x; + int step_y; + int side; + int tex_id; +} t_ray; + +typedef struct s_col +{ + int draw_start; + int draw_end; + int line_h; + double perp_dist; +} t_col; + +typedef struct s_texdraw +{ + int x; + t_ray *r; + t_tex *t; + t_col c; +} t_texdraw; + /* init.c */ -int init_window(t_game *g, int w, int h, char *title); -void cleanup_window(t_game *g); +int init_window(t_game *g, int w, int h, char *title); +void cleanup_window(t_game *g); /* hooks.c */ -int on_destroy(t_game *g); -int on_keydown(int key, t_game *g); -int on_keyup(int key, t_game *g); -void setup_hooks(t_game *g); +int on_destroy(t_game *g); +int on_keydown(int key, t_game *g); +int on_keyup(int key, t_game *g); +void setup_hooks(t_game *g); /* image.c */ -void img_put_pixel(t_img *img, int x, int y, int color); +void img_put_pixel(t_img *img, int x, int y, int color); /* draw.c */ -void draw_background(t_game *g); -void draw_vline(t_game *g, int x, int y0, int y1, int color); +void draw_background(t_game *g); +void draw_vline(t_game *g, int x, t_vline v); /* world.c */ -int world_init_demo(t_world *w); -void world_free(t_world *w); +// int world_init_demo(t_world *w); +void world_free(t_world *w); /* player.c */ -void player_init(t_game *g, double px, double py, double dx, double dy); -void player_update(t_game *g); +void player_init(t_game *g, t_player_init p); +void player_update(t_game *g); /* raycast.c */ -void raycast_frame(t_game *g); +void raycast_frame(t_game *g); /* loop.c */ -int game_loop(t_game *g); +int game_loop(t_game *g); /* textures.c */ -int textures_load(t_game *g, const char *no, const char *so, - const char *we, const char *ea); -void textures_free(t_game *g); -unsigned int tex_get_pixel(t_tex *t, int x, int y); +int textures_load(t_game *g, t_texpaths *paths); +void textures_free(t_game *g); +unsigned int tex_get_pixel(t_tex *t, int x, int y); /* draw.c */ -void draw_background(t_game *g); -void draw_vline(t_game *g, int x, int y0, int y1, int color); -void draw_tex_vline(t_game *g, int x, int y0, int y1, - t_tex *tex, int tex_x, double step, double tex_pos); - +void draw_background(t_game *g); +void draw_tex_vline(t_game *g, int x, t_texline l); +void draw_column(t_game *g, int x, t_ray *r); #endif diff --git a/maps/good/library.cub b/maps/good/library.cub index 37137ae..3d21b4d 100644 --- a/maps/good/library.cub +++ b/maps/good/library.cub @@ -8,10 +8,10 @@ EA assets/bookshelf_03.xpm 1111111111111111111 1001001001001001001 -1001001001001001001 +1001001001N01001001 1001001001001001001 1001001000001001001 -100000000S000000001 +1000000000000000001 1000011111111000001 1111000000000001111 1000000101010000001 diff --git a/maps/good/test.cub b/maps/good/test.cub index bcbe121..3d07838 100644 --- a/maps/good/test.cub +++ b/maps/good/test.cub @@ -16,7 +16,7 @@ F 200,200,200 10001 10001 10101 -1N01 +1E001 1001 10001 10001 diff --git a/srcs/exec/draw.c b/srcs/exec/draw.c index a440729..7e793f4 100644 --- a/srcs/exec/draw.c +++ b/srcs/exec/draw.c @@ -6,7 +6,7 @@ /* By: jle-neze +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/09/12 18:18:26 by jle-neze #+# #+# */ -/* Updated: 2025/09/12 18:18:52 by jle-neze ### ########.fr */ +/* Updated: 2025/10/29 15:30:00 by jle-neze ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,46 +14,67 @@ void draw_background(t_game *g) { - int x, y, half = g->gfx.h / 2; + int x; + int y; + int half; - for (y = 0; y < g->gfx.h; y++) + y = 0; + half = g->gfx.h / 2; + while (y < g->gfx.h) { - for (x = 0; x < g->gfx.w; x++) + x = 0; + while (x < g->gfx.w) { if (y < half) img_put_pixel(&g->gfx.frame, x, y, g->colors.ceil); else img_put_pixel(&g->gfx.frame, x, y, g->colors.floor); + x++; } + y++; } } -/* aussi exposée dans raycast.c, mais on garde la déclaration ici pour réutiliser ailleurs */ -void draw_vline(t_game *g, int x, int y0, int y1, int color) +void draw_vline(t_game *g, int x, t_vline v) { - if (y0 < 0) y0 = 0; - if (y1 >= g->gfx.h) y1 = g->gfx.h - 1; - for (int y = y0; y <= y1; y++) - img_put_pixel(&g->gfx.frame, x, y, color); + int y; + + if (v.y0 < 0) + v.y0 = 0; + if (v.y1 >= g->gfx.h) + v.y1 = g->gfx.h - 1; + y = v.y0; + while (y <= v.y1) + { + img_put_pixel(&g->gfx.frame, x, y, v.color); + y++; + } } -void draw_tex_vline(t_game *g, int x, int y0, int y1, - t_tex *tex, int tex_x, double step, double tex_pos) +void draw_tex_vline(t_game *g, int x, t_texline l) { - if (y0 < 0) + int y; + int tex_y; + unsigned int color; + + if (l.y0 < 0) { - tex_pos += step * (-y0); - y0 = 0; + l.tex_pos += l.step * (-l.y0); + l.y0 = 0; } - if (y1 >= g->gfx.h) - y1 = g->gfx.h - 1; - for (int y = y0; y <= y1; y++) + if (l.y1 >= g->gfx.h) + l.y1 = g->gfx.h - 1; + y = l.y0; + while (y <= l.y1) { - int tex_y = (int)tex_pos; - if (tex_y < 0) tex_y = 0; - if (tex_y >= tex->h) tex_y = tex->h - 1; - unsigned int color = tex_get_pixel(tex, tex_x, tex_y); + tex_y = (int)l.tex_pos; + if (tex_y < 0) + tex_y = 0; + if (tex_y >= l.tex->h) + tex_y = l.tex->h - 1; + color = tex_get_pixel(l.tex, l.tex_x, tex_y); img_put_pixel(&g->gfx.frame, x, y, (int)color); - tex_pos += step; + l.tex_pos += l.step; + y++; } } diff --git a/srcs/exec/hooks.c b/srcs/exec/hooks.c index 1e2cb0e..73d8a95 100644 --- a/srcs/exec/hooks.c +++ b/srcs/exec/hooks.c @@ -19,7 +19,6 @@ int on_destroy(t_game *g) textures_free(g); cleanup_window(g); world_free(&g->world); - /* Libérer data si disponible */ if (g->data) { free_textures(g->data->texture); @@ -29,15 +28,20 @@ int on_destroy(t_game *g) return (0); } - -static void set_key(int key, t_game *g, int press) +static void set_key(int key, t_game *g, int press) { - if (key == KEY_W) g->in.w = press; - if (key == KEY_A) g->in.a = press; - if (key == KEY_S) g->in.s = press; - if (key == KEY_D) g->in.d = press; - if (key == KEY_LEFT) g->in.left = press; - if (key == KEY_RIGHT) g->in.right = press; + if (key == KEY_W) + g->in.w = press; + if (key == KEY_A) + g->in.a = press; + if (key == KEY_S) + g->in.s = press; + if (key == KEY_D) + g->in.d = press; + if (key == KEY_LEFT) + g->in.left = press; + if (key == KEY_RIGHT) + g->in.right = press; } int on_keydown(int key, t_game *g) @@ -56,11 +60,8 @@ int on_keyup(int key, t_game *g) void setup_hooks(t_game *g) { - /* croix de fermeture */ mlx_hook(g->gfx.win, 17, 0, on_destroy, g); - /* KeyPress / KeyRelease */ - mlx_hook(g->gfx.win, 2, 1L<<0, on_keydown, g); - mlx_hook(g->gfx.win, 3, 1L<<1, on_keyup, g); - /* boucle */ + mlx_hook(g->gfx.win, 2, 1L << 0, on_keydown, g); + mlx_hook(g->gfx.win, 3, 1L << 1, on_keyup, g); mlx_loop_hook(g->gfx.mlx, game_loop, g); } diff --git a/srcs/exec/init.c b/srcs/exec/init.c index 3c5d1ac..dc9f04e 100644 --- a/srcs/exec/init.c +++ b/srcs/exec/init.c @@ -52,4 +52,4 @@ void cleanup_window(t_game *g) free(g->gfx.mlx); g->gfx.mlx = NULL; } -} \ No newline at end of file +} diff --git a/srcs/exec/loop.c b/srcs/exec/loop.c index 883b4e1..4264bd2 100644 --- a/srcs/exec/loop.c +++ b/srcs/exec/loop.c @@ -14,12 +14,9 @@ int game_loop(t_game *g) { - /* 1) Update joueur selon input */ player_update(g); - /* 2) Dessin */ draw_background(g); raycast_frame(g); mlx_put_image_to_window(g->gfx.mlx, g->gfx.win, g->gfx.frame.ptr, 0, 0); return (0); } -/* Note: on pourrait optimiser en ne redessinant que ce qui change */ diff --git a/srcs/exec/player.c b/srcs/exec/player.c index 8e9311f..7336cce 100644 --- a/srcs/exec/player.c +++ b/srcs/exec/player.c @@ -5,76 +5,73 @@ /* +:+ +:+ +:+ */ /* By: jle-neze +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/09/12 18:24:21 by jle-neze #+# #+# */ -/* Updated: 2025/09/12 18:24:22 by jle-neze ### ########.fr */ +/* Created: 2025/10/28 16:20:00 by jle-neze #+# #+# */ +/* Updated: 2025/10/28 16:20:00 by jle-neze ### ########.fr */ /* */ /* ************************************************************************** */ #include "cub.h" +#include -void player_init(t_game *g, double px, double py, double dx, double dy) +void player_init(t_game *g, t_player_init p) { - g->cam.pos_x = px; - g->cam.pos_y = py; - g->cam.dir_x = dx; - g->cam.dir_y = dy; - /* FOV ≈ 66° → plane perpendiculaire (0.66) */ - g->cam.plane_x = -dy * 0.66; - g->cam.plane_y = dx * 0.66; - g->move_speed = 0.07; /* ajuste si besoin */ - g->rot_speed = 0.05; /* rad/frame */ + g->cam.pos_x = p.px; + g->cam.pos_y = p.py; + g->cam.dir_x = p.dx; + g->cam.dir_y = p.dy; + g->cam.plane_x = -p.dy * 0.66; + g->cam.plane_y = p.dx * 0.66; + g->move_speed = 0.03; + g->rot_speed = 0.05; } -/* petits helpers collision */ -static int is_wall(t_world *w, int mx, int my) +static int is_wall(t_world *w, int mx, int my) { - if (mx < 0 || my < 0 || mx >= w->w || my >= w->h) return (1); + if (mx < 0 || my < 0 || mx >= w->w || my >= w->h) + return (1); return (w->grid[my][mx] == '1'); } +static void player_move(t_game *g, double dx, double dy) +{ + double nx; + double ny; + + nx = g->cam.pos_x + dx * g->move_speed; + ny = g->cam.pos_y + dy * g->move_speed; + if (!is_wall(&g->world, (int)nx, (int)g->cam.pos_y)) + g->cam.pos_x = nx; + if (!is_wall(&g->world, (int)g->cam.pos_x, (int)ny)) + g->cam.pos_y = ny; +} + +static void player_rotate(t_game *g, int dir) +{ + double rs; + double old_dir_x; + double old_plane_x; + + rs = g->rot_speed * (dir); + old_dir_x = g->cam.dir_x; + g->cam.dir_x = g->cam.dir_x * cos(rs) - g->cam.dir_y * sin(rs); + g->cam.dir_y = old_dir_x * sin(rs) + g->cam.dir_y * cos(rs); + old_plane_x = g->cam.plane_x; + g->cam.plane_x = g->cam.plane_x * cos(rs) - g->cam.plane_y * sin(rs); + g->cam.plane_y = old_plane_x * sin(rs) + g->cam.plane_y * cos(rs); +} + void player_update(t_game *g) { - double nx, ny; - - /* Avancer/retour W/S */ if (g->in.w) - { - nx = g->cam.pos_x + g->cam.dir_x * g->move_speed; - ny = g->cam.pos_y + g->cam.dir_y * g->move_speed; - if (!is_wall(&g->world, (int)nx, (int)g->cam.pos_y)) g->cam.pos_x = nx; - if (!is_wall(&g->world, (int)g->cam.pos_x, (int)ny)) g->cam.pos_y = ny; - } + player_move(g, g->cam.dir_x, g->cam.dir_y); if (g->in.s) - { - nx = g->cam.pos_x - g->cam.dir_x * g->move_speed; - ny = g->cam.pos_y - g->cam.dir_y * g->move_speed; - if (!is_wall(&g->world, (int)nx, (int)g->cam.pos_y)) g->cam.pos_x = nx; - if (!is_wall(&g->world, (int)g->cam.pos_x, (int)ny)) g->cam.pos_y = ny; - } - /* Strafe A/D (gauche/droite) */ + player_move(g, -g->cam.dir_x, -g->cam.dir_y); if (g->in.a) - { - nx = g->cam.pos_x - g->cam.dir_y * g->move_speed; - ny = g->cam.pos_y + g->cam.dir_x * g->move_speed; - if (!is_wall(&g->world, (int)nx, (int)g->cam.pos_y)) g->cam.pos_x = nx; - if (!is_wall(&g->world, (int)g->cam.pos_x, (int)ny)) g->cam.pos_y = ny; - } + player_move(g, -g->cam.dir_y, g->cam.dir_x); if (g->in.d) - { - nx = g->cam.pos_x + g->cam.dir_y * g->move_speed; - ny = g->cam.pos_y - g->cam.dir_x * g->move_speed; - if (!is_wall(&g->world, (int)nx, (int)g->cam.pos_y)) g->cam.pos_x = nx; - if (!is_wall(&g->world, (int)g->cam.pos_x, (int)ny)) g->cam.pos_y = ny; - } - /* Rotation gauche/droite */ - if (g->in.left || g->in.right) - { - double rs = g->rot_speed * (g->in.right ? 1.0 : -1.0); - double old_dir_x = g->cam.dir_x; - g->cam.dir_x = g->cam.dir_x * cos(rs) - g->cam.dir_y * sin(rs); - g->cam.dir_y = old_dir_x * sin(rs) + g->cam.dir_y * cos(rs); - double old_plane_x = g->cam.plane_x; - g->cam.plane_x = g->cam.plane_x * cos(rs) - g->cam.plane_y * sin(rs); - g->cam.plane_y = old_plane_x * sin(rs) + g->cam.plane_y * cos(rs); - } + player_move(g, g->cam.dir_y, -g->cam.dir_x); + if (g->in.left) + player_rotate(g, -1); + else if (g->in.right) + player_rotate(g, 1); } diff --git a/srcs/exec/raycast.c b/srcs/exec/raycast.c index be707b0..a0d3733 100644 --- a/srcs/exec/raycast.c +++ b/srcs/exec/raycast.c @@ -5,239 +5,94 @@ /* +:+ +:+ +:+ */ /* By: jle-neze +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/09/12 18:24:37 by jle-neze #+# #+# */ -/* Updated: 2025/10/26 02:20:06 by lfirmin ### ########.fr */ +/* Created: 2025/10/29 18:15:00 by jle-neze #+# #+# */ +/* Updated: 2025/10/29 18:15:00 by jle-neze ### ########.fr */ /* */ /* ************************************************************************** */ #include "cub.h" -// /* petite fonction utilitaire: trace une ligne verticale remplie */ -// void draw_vline(t_game *g, int x, int y0, int y1, int color) -// { -// if (y0 < 0) y0 = 0; -// if (y1 >= g->gfx.h) y1 = g->gfx.h - 1; -// for (int y = y0; y <= y1; y++) -// img_put_pixel(&g->gfx.frame, x, y, color); -// } - -/* Version 1: simple couleurs */ -// void raycast_frame(t_game *g) -// { -// for (int x = 0; x < g->gfx.w; x++) -// { -// double camera_x = 2.0 * x / (double)g->gfx.w - 1.0; -// double ray_dir_x = g->cam.dir_x + g->cam.plane_x * camera_x; -// double ray_dir_y = g->cam.dir_y + g->cam.plane_y * camera_x; - -// int map_x = (int)g->cam.pos_x; -// int map_y = (int)g->cam.pos_y; - -// double delta_dist_x = (ray_dir_x == 0) ? 1e30 : fabs(1.0 / ray_dir_x); -// double delta_dist_y = (ray_dir_y == 0) ? 1e30 : fabs(1.0 / ray_dir_y); - -// int step_x, step_y; -// double side_dist_x, side_dist_y; - -// if (ray_dir_x < 0) -// { -// step_x = -1; -// side_dist_x = (g->cam.pos_x - map_x) * delta_dist_x; -// } -// else -// { -// step_x = 1; -// side_dist_x = (map_x + 1.0 - g->cam.pos_x) * delta_dist_x; -// } -// if (ray_dir_y < 0) -// { -// step_y = -1; -// side_dist_y = (g->cam.pos_y - map_y) * delta_dist_y; -// } -// else -// { -// step_y = 1; -// side_dist_y = (map_y + 1.0 - g->cam.pos_y) * delta_dist_y; -// } - -// int hit = 0; -// int side = 0; /* 0:x, 1:y */ - -// while (!hit) -// { -// if (side_dist_x < side_dist_y) -// { -// side_dist_x += delta_dist_x; -// map_x += step_x; -// side = 0; -// } -// else -// { -// side_dist_y += delta_dist_y; -// map_y += step_y; -// side = 1; -// } -// if (map_x < 0 || map_y < 0 || map_x >= g->world.w || map_y >= g->world.h -// || g->world.grid[map_y][map_x] == '1') -// hit = 1; -// } -// double perp_wall_dist; -// if (side == 0) -// perp_wall_dist = (side_dist_x - delta_dist_x); -// else -// perp_wall_dist = (side_dist_y - delta_dist_y); - -// int line_h = (int)(g->gfx.h / (perp_wall_dist > 1e-6 ? perp_wall_dist : 1e-6)); -// int draw_start = -line_h / 2 + g->gfx.h / 2; -// int draw_end = line_h / 2 + g->gfx.h / 2; - -// /* Couleur: simple code NSEW selon step & side */ -// int color_idx; -// if (side == 0) -// color_idx = (step_x < 0) ? 2 /* E */ : 3 /* W */; -// else -// color_idx = (step_y < 0) ? 1 /* S */ : 0 /* N */; - -// int color = g->colors.wall_nsew[color_idx]; -// if (side == 1) color = (color & 0xFEFEFE) >> 1; /* ombre simple */ - -// draw_vline(g, x, draw_start, draw_end, color); -// } -// } - -/* 2eme test de la meme focntion (pas encore choisi laquelle)*/ -// void raycast_frame(t_game *g) -// { -// for (int x = 0; x < g->gfx.w; x++) -// { -// double camera_x = 2.0 * x / (double)g->gfx.w - 1.0; -// double ray_dir_x = g->cam.dir_x + g->cam.plane_x * camera_x; -// double ray_dir_y = g->cam.dir_y + g->cam.plane_y * camera_x; - -// int map_x = (int)g->cam.pos_x; -// int map_y = (int)g->cam.pos_y; - -// double delta_dist_x = (ray_dir_x == 0) ? 1e30 : fabs(1.0 / ray_dir_x); -// double delta_dist_y = (ray_dir_y == 0) ? 1e30 : fabs(1.0 / ray_dir_y); - -// int step_x, step_y; -// double side_dist_x, side_dist_y; - -// if (ray_dir_x < 0) { step_x = -1; side_dist_x = (g->cam.pos_x - map_x) * delta_dist_x; } -// else { step_x = 1; side_dist_x = (map_x + 1.0 - g->cam.pos_x) * delta_dist_x; } -// if (ray_dir_y < 0) { step_y = -1; side_dist_y = (g->cam.pos_y - map_y) * delta_dist_y; } -// else { step_y = 1; side_dist_y = (map_y + 1.0 - g->cam.pos_y) * delta_dist_y; } - -// int hit = 0, side = 0; -// while (!hit) -// { -// if (side_dist_x < side_dist_y) { side_dist_x += delta_dist_x; map_x += step_x; side = 0; } -// else { side_dist_y += delta_dist_y; map_y += step_y; side = 1; } -// if (map_x < 0 || map_y < 0 || map_x >= g->world.w || map_y >= g->world.h -// || g->world.grid[map_y][map_x] == '1') -// hit = 1; -// } - -// double perp_wall_dist = (side == 0) ? (side_dist_x - delta_dist_x) : (side_dist_y - delta_dist_y); -// if (perp_wall_dist < 1e-6) perp_wall_dist = 1e-6; - -// int line_h = (int)(g->gfx.h / perp_wall_dist); -// int draw_start = -line_h / 2 + g->gfx.h / 2; -// int draw_end = line_h / 2 + g->gfx.h / 2; - -// int color_idx; -// if (side == 0) color_idx = (step_x < 0) ? 2 /* E */ : 3 /* W */; -// else color_idx = (step_y < 0) ? 1 /* S */ : 0 /* N */; - -// int color = g->colors.wall_nsew[color_idx]; -// if (side == 1) color = (color & 0xFEFEFE) >> 1; /* ombre simple */ - -// draw_vline(g, x, draw_start, draw_end, color); /* impl. dans draw.c */ -// } -// } - -/* Version 3: textures */ -void raycast_frame(t_game *g) +static void init_ray_vars(t_game *g, int x, t_ray *r) { - const double EPS = 1e-6; + double cam; - for (int x = 0; x < g->gfx.w; x++) + cam = 2.0 * x / (double)g->gfx.w - 1.0; + r->ray_dir_x = g->cam.dir_x + g->cam.plane_x * cam; + r->ray_dir_y = g->cam.dir_y + g->cam.plane_y * cam; + r->map_x = (int)g->cam.pos_x; + r->map_y = (int)g->cam.pos_y; + if (r->ray_dir_x == 0) + r->delta_dist_x = 1e30; + else + r->delta_dist_x = fabs(1.0 / r->ray_dir_x); + if (r->ray_dir_y == 0) + r->delta_dist_y = 1e30; + else + r->delta_dist_y = fabs(1.0 / r->ray_dir_y); +} + +static void calc_step_side(t_game *g, t_ray *r) +{ + if (r->ray_dir_x < 0) { - double camera_x = 2.0 * x / (double)g->gfx.w - 1.0; - double ray_dir_x = g->cam.dir_x + g->cam.plane_x * camera_x; - double ray_dir_y = g->cam.dir_y + g->cam.plane_y * camera_x; - - int map_x = (int)g->cam.pos_x; - int map_y = (int)g->cam.pos_y; - - double delta_dist_x = (ray_dir_x == 0) ? 1e30 : fabs(1.0 / ray_dir_x); - double delta_dist_y = (ray_dir_y == 0) ? 1e30 : fabs(1.0 / ray_dir_y); - - int step_x, step_y; - double side_dist_x, side_dist_y; - - if (ray_dir_x < 0) { step_x = -1; side_dist_x = (g->cam.pos_x - map_x) * delta_dist_x; } - else { step_x = 1; side_dist_x = (map_x + 1.0 - g->cam.pos_x) * delta_dist_x; } - if (ray_dir_y < 0) { step_y = -1; side_dist_y = (g->cam.pos_y - map_y) * delta_dist_y; } - else { step_y = 1; side_dist_y = (map_y + 1.0 - g->cam.pos_y) * delta_dist_y; } - - int hit = 0, side = 0; - while (!hit) - { - if (side_dist_x < side_dist_y) { side_dist_x += delta_dist_x; map_x += step_x; side = 0; } - else { side_dist_y += delta_dist_y; map_y += step_y; side = 1; } - if (map_x < 0 || map_y < 0 || map_x >= g->world.w || map_y >= g->world.h - || g->world.grid[map_y][map_x] == '1') - hit = 1; - } - - double perp_wall_dist = (side == 0) ? (side_dist_x - delta_dist_x) : (side_dist_y - delta_dist_y); - if (perp_wall_dist < EPS) perp_wall_dist = EPS; - - int line_h = (int)(g->gfx.h / perp_wall_dist); - int draw_start = -line_h / 2 + g->gfx.h / 2; - int draw_end = line_h / 2 + g->gfx.h / 2; - - /* Choix de texture 0:N 1:S 2:E 3:W (même logique que couleurs) */ - int tex_id; - if (side == 0) tex_id = (step_x < 0) ? 2 /* E */ : 3 /* W */; - else tex_id = (step_y < 0) ? 1 /* S */ : 0 /* N */; - - if (!g->has_tex) - { - int color = g->colors.wall_nsew[tex_id]; - if (side == 1) color = (color & 0xFEFEFE) >> 1; - draw_vline(g, x, draw_start, draw_end, color); - continue; - } - - /* --- TEXTURE MAPPING --- */ - t_tex *t = &g->tex[tex_id]; - - /* Position exacte du hit sur le mur (0..1) */ - double wall_x; - if (side == 0) - wall_x = g->cam.pos_y + perp_wall_dist * ray_dir_y; - else - wall_x = g->cam.pos_x + perp_wall_dist * ray_dir_x; - wall_x -= floor(wall_x); - - /* Coordonnée X dans la texture */ - int tex_x = (int)(wall_x * (double)t->w); - if (side == 0 && ray_dir_x > 0) tex_x = t->w - tex_x - 1; - if (side == 1 && ray_dir_y < 0) tex_x = t->w - tex_x - 1; - - /* Échantillonnage vertical */ - double step = (double)t->h / (double)line_h; - double tex_pos = (draw_start - g->gfx.h / 2 + line_h / 2) * step; - - /* Ombre légère sur faces Y (optionnel) */ - draw_tex_vline(g, x, draw_start, draw_end, t, tex_x, step, tex_pos); - if (side == 1) { - /* sombrement simple: on pourrait parcourir y et foncer; plus simple: rien faire - pour rester portable / endianness-safe. */ - } + r->step_x = -1; + r->side_dist_x = (g->cam.pos_x - r->map_x) * r->delta_dist_x; + } + else + { + r->step_x = 1; + r->side_dist_x = (r->map_x + 1.0 - g->cam.pos_x) * r->delta_dist_x; + } + if (r->ray_dir_y < 0) + { + r->step_y = -1; + r->side_dist_y = (g->cam.pos_y - r->map_y) * r->delta_dist_y; + } + else + { + r->step_y = 1; + r->side_dist_y = (r->map_y + 1.0 - g->cam.pos_y) * r->delta_dist_y; } } +static void perform_dda(t_game *g, t_ray *r) +{ + int hit; + hit = 0; + while (!hit) + { + if (r->side_dist_x < r->side_dist_y) + { + r->side_dist_x += r->delta_dist_x; + r->map_x += r->step_x; + r->side = 0; + } + else + { + r->side_dist_y += r->delta_dist_y; + r->map_y += r->step_y; + r->side = 1; + } + if (r->map_x < 0 || r->map_y < 0 || r->map_x >= g->world.w + || r->map_y >= g->world.h + || g->world.grid[r->map_y][r->map_x] == '1') + hit = 1; + } +} + +void raycast_frame(t_game *g) +{ + int x; + t_ray r; + + x = 0; + while (x < g->gfx.w) + { + init_ray_vars(g, x, &r); + calc_step_side(g, &r); + perform_dda(g, &r); + draw_column(g, x, &r); + x++; + } +} diff --git a/srcs/exec/raycast_utils.c b/srcs/exec/raycast_utils.c new file mode 100644 index 0000000..035132e --- /dev/null +++ b/srcs/exec/raycast_utils.c @@ -0,0 +1,97 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* raycast_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jle-neze +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/10/29 18:20:00 by jle-neze #+# #+# */ +/* Updated: 2025/10/29 18:20:00 by jle-neze ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "cub.h" + +static void draw_textured(t_game *g, t_texdraw d) +{ + double wall_x; + int tex_x; + double step; + double tex_pos; + t_texline l; + + if (d.r->side == 0) + wall_x = g->cam.pos_y + d.c.perp_dist * d.r->ray_dir_y; + else + wall_x = g->cam.pos_x + d.c.perp_dist * d.r->ray_dir_x; + wall_x -= floor(wall_x); + tex_x = (int)(wall_x * (double)d.t->w); + if ((d.r->side == 0 && d.r->ray_dir_x > 0) + || (d.r->side == 1 && d.r->ray_dir_y < 0)) + tex_x = d.t->w - tex_x - 1; + step = (double)d.t->h / (double)d.c.line_h; + tex_pos = (d.c.draw_start - g->gfx.h / 2 + d.c.line_h / 2) * step; + l.tex = d.t; + l.tex_x = tex_x; + l.step = step; + l.tex_pos = tex_pos; + l.y0 = d.c.draw_start; + l.y1 = d.c.draw_end; + draw_tex_vline(g, d.x, l); +} + +static void set_tex_id(t_ray *r) +{ + if (r->side == 0) + { + if (r->step_x < 0) + r->tex_id = 2; + else + r->tex_id = 3; + } + else + { + if (r->step_y < 0) + r->tex_id = 1; + else + r->tex_id = 0; + } +} + +static void draw_color_column(t_game *g, int x, t_ray *r, t_col c) +{ + t_vline v; + + v.y0 = c.draw_start; + v.y1 = c.draw_end; + v.color = g->colors.wall_nsew[r->tex_id]; + if (r->side == 1) + v.color = (v.color & 0xFEFEFE) >> 1; + draw_vline(g, x, v); +} + +void draw_column(t_game *g, int x, t_ray *r) +{ + t_tex *t; + t_col c; + t_texdraw d; + + if (r->side == 0) + c.perp_dist = r->side_dist_x - r->delta_dist_x; + else + c.perp_dist = r->side_dist_y - r->delta_dist_y; + if (c.perp_dist < 1e-6) + c.perp_dist = 1e-6; + c.line_h = (int)(g->gfx.h / c.perp_dist); + c.draw_start = -c.line_h / 2 + g->gfx.h / 2; + c.draw_end = c.line_h / 2 + g->gfx.h / 2; + set_tex_id(r); + if (!g->has_tex) + return (draw_color_column(g, x, r, c)); + t = &g->tex[r->tex_id]; + d.x = x; + d.r = r; + d.t = t; + d.c = c; + draw_textured(g, d); +} diff --git a/srcs/exec/textures.c b/srcs/exec/textures.c index 1f79947..3448eab 100644 --- a/srcs/exec/textures.c +++ b/srcs/exec/textures.c @@ -21,13 +21,12 @@ static int load_one(t_game *g, t_tex *t, const char *path) return (0); } -int textures_load(t_game *g, const char *no, const char *so, - const char *we, const char *ea) +int textures_load(t_game *g, t_texpaths *paths) { - if (load_one(g, &g->tex[0], no) - || load_one(g, &g->tex[1], so) - || load_one(g, &g->tex[2], we) - || load_one(g, &g->tex[3], ea)) + if (load_one(g, &g->tex[0], paths->no) + || load_one(g, &g->tex[1], paths->so) + || load_one(g, &g->tex[2], paths->we) + || load_one(g, &g->tex[3], paths->ea)) { textures_free(g); return (1); @@ -38,16 +37,22 @@ int textures_load(t_game *g, const char *no, const char *so, void textures_free(t_game *g) { - for (int i = 0; i < 4; i++) + int i; + + i = 0; + while (i < 4) { if (g->tex[i].ptr) mlx_destroy_image(g->gfx.mlx, g->tex[i].ptr); g->tex[i].ptr = NULL; + i++; } } unsigned int tex_get_pixel(t_tex *t, int x, int y) { - char *px = t->addr + (y * t->line_len + x * (t->bpp / 8)); + char *px; + + px = t->addr + (y * t->line_len + x * (t->bpp / 8)); return (*(unsigned int *)px); } diff --git a/srcs/exec/world.c b/srcs/exec/world.c index 4dae474..709d00c 100644 --- a/srcs/exec/world.c +++ b/srcs/exec/world.c @@ -25,57 +25,64 @@ // "111111111111", // NULL // }; -static const char *demo_map[] = { - "111111111111", - "100000000001", - "100000000001", - "100000000001", - "100000001111", - "100000000001", - "100000000001", /* N = start dir nord, on l'ignore ici (juste info) */ - "100000000001", - "111111111111", - NULL -}; +// static const char *demo_map[] = { +// "111111111111", +// "100000000001", +// "100000000001", +// "100000000001", +// "100000001111", +// "100000000001", +// "100000000001", /* N = start dir nord, on l'ignore ici (juste info) */ +// "100000000001", +// "111111111111", +// NULL +// }; -int world_init_demo(t_world *w) -{ - int h = 0; - while (demo_map[h]) - h++; - w->h = h; - w->w = 0; - for (int i = 0; i < h; i++) - { - int len = 0; - while (demo_map[i][len]) len++; - if (len > w->w) w->w = len; - } - w->grid = (char **)malloc(sizeof(char *) * (h + 1)); - if (!w->grid) return (1); - for (int y = 0; y < h; y++) - { - w->grid[y] = (char *)malloc(w->w + 1); - if (!w->grid[y]) return (1); - for (int x = 0; x < w->w; x++) - { - char c = demo_map[y][x]; - if (c == 0) c = '1'; - if (c == 'N' || c == 'S' || c == 'E' || c == 'W') - c = '0'; - w->grid[y][x] = c; - } - w->grid[y][w->w] = '\0'; - } - w->grid[h] = NULL; - return (0); -} +// int world_init_demo(t_world *w) +// { +// int h = 0; +// while (demo_map[h]) +// h++; +// w->h = h; +// w->w = 0; +// for (int i = 0; i < h; i++) +// { +// int len = 0; +// while (demo_map[i][len]) len++; +// if (len > w->w) w->w = len; +// } +// w->grid = (char **)malloc(sizeof(char *) * (h + 1)); +// if (!w->grid) return (1); +// for (int y = 0; y < h; y++) +// { +// w->grid[y] = (char *)malloc(w->w + 1); +// if (!w->grid[y]) return (1); +// for (int x = 0; x < w->w; x++) +// { +// char c = demo_map[y][x]; +// if (c == 0) c = '1'; +// if (c == 'N' || c == 'S' || c == 'E' || c == 'W') +// c = '0'; +// w->grid[y][x] = c; +// } +// w->grid[y][w->w] = '\0'; +// } +// w->grid[h] = NULL; +// return (0); +// } void world_free(t_world *w) { - if (!w->grid) return ; - for (int y = 0; y < w->h; y++) + int y; + + if (!w->grid) + return ; + y = 0; + while (y < w->h) + { free(w->grid[y]); + y++; + } free(w->grid); w->grid = NULL; } diff --git a/srcs/main.c b/srcs/main.c index 7f205fa..b43a3c3 100644 --- a/srcs/main.c +++ b/srcs/main.c @@ -6,142 +6,28 @@ /* By: lfirmin +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/08/22 14:56:25 by lfirmin #+# #+# */ -/* Updated: 2025/10/08 16:25:42 by lfirmin ### ########.fr */ +/* Updated: 2025/11/03 09:06:01 by lfirmin ### ########.fr */ /* */ /* ************************************************************************** */ #include "cub.h" -// void print_int_array(int *array, int size) -// { -// int i; - -// if (!array) -// return ; -// i = 0; -// while (i < size) -// { -// ft_putnbr_fd(array[i], 1); -// if (i < size - 1) -// write(1, ", ", 2); -// i++; -// } -// write(1, "\n", 1); -// } -// void debug(t_data data) -// { -// printf("map:\n\n"); -// print_array(data.map); -// printf("\n"); -// printf("c: "); -// fflush(stdout); -// print_int_array(data.texture->ceiling, 3); -// printf("f: "); -// fflush(stdout); -// print_int_array(data.texture->floor, 3); -// printf("p: "); -// fflush(stdout); -// print_int_array(data.parsing.player, 3); -// printf("\n"); -// printf("\ntexture:\n\n"); -// printf("%s\n", data.texture->east); -// printf("%s\n", data.texture->north); -// printf("%s\n", data.texture->west); -// printf("%s\n", data.texture->south); -// } - -// int main(int ac, char **av) -// { -// t_data data; - -// init_data(&data, av[1]); -// if (parsing(&data)); -// debug(data); -// free_char_array(data.parsing.raw_map); -// free_textures(data.texture); -// free_data(&data); -// } - -int rgb_to_int(int r, int g, int b) +int setup_and_run(t_game *g, t_data *data) { - if (r < 0) r = 0; - if (r > 255) r = 255; - if (g < 0) g = 0; - if (g > 255) g = 255; - if (b < 0) b = 0; - if (b > 255) b = 255; - return ((r << 16) | (g << 8) | b); -} + t_player_init p; -static int world_init_from_parsing(t_world *world, t_data *data) -{ - int y; - - world->h = 0; - while (data->map[world->h]) - world->h++; - world->w = ft_strlen(data->map[0]); - - world->grid = malloc(sizeof(char *) * (world->h + 1)); - if (!world->grid) + p.px = data->parsing.player[0] + 0.5; + p.py = data->parsing.player[1] + 0.5; + init_player_direction(&p, data->parsing.player[2]); + player_init(g, p); + if (init_mlx_and_textures(g, data) != 0) return (1); - y = 0; - while (y < world->h) - { - world->grid[y] = ft_strdup(data->map[y]); - if (!world->grid[y]) - return (1); - y++; - } - world->grid[world->h] = NULL; + g->data = data; + setup_hooks(g); + get_next_line(-2); + mlx_loop(g->gfx.mlx); return (0); } - -// int main(int ac, char **av) -// { -// t_game g; -// t_data data; - -// if (ac != 2) -// return (printf("Usage: ./cub3d \n"), 1); - -// init_data(&data, av[1]); -// if (parsing(&data)) -// return (printf("Parsing error\n"), 1); -// free_char_array(data.parsing.raw_map); - -// /* init couleurs et textures */ -// g.colors.floor = rgb_to_int(data.texture->floor[0], data.texture->floor[1], data.texture->floor[2]); // ok jai change le fonction rgb_to_int elle attend 3 int le r le g et le b -// g.colors.ceil = rgb_to_int(data.texture->ceiling[0], data.texture->ceiling[1], data.texture->ceiling[2]); -// if (textures_load(&g, -// data.texture->north, data.texture->south, -// data.texture->west, data.texture->east) != 0) -// g.has_tex = 0; - -// /* init map et player */ -// if (world_init_from_parsing(&g.world, &data) != 0) -// return (printf("World init failed\n"), 1); -// double dx = 0, dy = 0; -// if (data.parsing.player[2] == 'N') dy = -1; -// if (data.parsing.player[2] == 'S') dy = 1; -// if (data.parsing.player[2] == 'E') dx = 1; -// if (data.parsing.player[2] == 'W') dx = -1; -// player_init(&g, -// data.parsing.player[0] + 0.5, -// data.parsing.player[1] + 0.5, -// dx, dy); - -// /* window + loop */ -// if (init_window(&g, 1024, 768, "cub3D") != 0) -// return (1); -// setup_hooks(&g); -// mlx_loop(g.gfx.mlx); - -// world_free(&g.world); -// free_data(&data); -// return (0); -// } - int main(int ac, char **av) { t_game g; @@ -149,59 +35,12 @@ int main(int ac, char **av) if (ac != 2) return (printf("Usage: ./cub3d \n"), 1); - - memset(&g, 0, sizeof(t_game)); // IMPORTANT : initialiser g - - init_data(&data, av[1]); - if (parsing(&data)) - { - free_textures(data.texture); - free_data(&data); + if (init_game_data(&g, &data, av[1]) != 0) return (1); - } - - /* init couleurs */ - g.colors.floor = rgb_to_int(data.texture->floor[0], data.texture->floor[1], data.texture->floor[2]); - g.colors.ceil = rgb_to_int(data.texture->ceiling[0], data.texture->ceiling[1], data.texture->ceiling[2]); - - /* init map et player */ - if (world_init_from_parsing(&g.world, &data) != 0) - return (printf("World init failed\n"), 1); - /* Libérer data->map après la duplication vers world->grid */ - free_char_array(data.map); - data.map = NULL; - - double dx = 0, dy = 0; - if (data.parsing.player[2] == 'S') dy = -1; - if (data.parsing.player[2] == 'N') dy = 1; - if (data.parsing.player[2] == 'E') dx = 1; - if (data.parsing.player[2] == 'W') dx = -1; - player_init(&g, - data.parsing.player[0] + 0.5, - data.parsing.player[1] + 0.5, - dx, dy); - - /* window AVANT textures ! */ - if (init_window(&g, 1024, 768, "cub3D") != 0) + if (setup_and_run(&g, &data) != 0) return (1); - - /* MAINTENANT on charge les textures */ - if (textures_load(&g, - data.texture->north, data.texture->south, - data.texture->west, data.texture->east) != 0) - g.has_tex = 0; - - /* Passer data à g pour le cleanup */ - g.data = &data; - - setup_hooks(&g); - /* Vider le buffer gnl avant de rentrer dans mlx_loop */ - get_next_line(-2); - mlx_loop(g.gfx.mlx); - world_free(&g.world); free_textures(data.texture); free_data(&data); - return (0); -} \ No newline at end of file +} diff --git a/srcs/main.c_old b/srcs/main.c_old new file mode 100644 index 0000000..41fb66f --- /dev/null +++ b/srcs/main.c_old @@ -0,0 +1,218 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* main.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lfirmin +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/08/22 14:56:25 by lfirmin #+# #+# */ +/* Updated: 2025/11/03 08:32:46 by lfirmin ### ########.fr */ +/* */ +/* ************************************************************************** */ +#include "cub.h" + +// void print_int_array(int *array, int size) +// { +// int i; + +// if (!array) +// return ; +// i = 0; +// while (i < size) +// { +// ft_putnbr_fd(array[i], 1); +// if (i < size - 1) +// write(1, ", ", 2); +// i++; +// } +// write(1, "\n", 1); +// } +// void debug(t_data data) +// { +// printf("map:\n\n"); +// print_array(data.map); +// printf("\n"); +// printf("c: "); +// fflush(stdout); +// print_int_array(data.texture->ceiling, 3); +// printf("f: "); +// fflush(stdout); +// print_int_array(data.texture->floor, 3); +// printf("p: "); +// fflush(stdout); +// print_int_array(data.parsing.player, 3); +// printf("\n"); +// printf("\ntexture:\n\n"); +// printf("%s\n", data.texture->east); +// printf("%s\n", data.texture->north); +// printf("%s\n", data.texture->west); +// printf("%s\n", data.texture->south); +// } + +// int main(int ac, char **av) +// { +// t_data data; + +// init_data(&data, av[1]); +// if (parsing(&data)); +// debug(data); +// free_char_array(data.parsing.raw_map); +// free_textures(data.texture); +// free_data(&data); +// } + +int rgb_to_int(int r, int g, int b) +{ + if (r < 0) r = 0; + if (r > 255) r = 255; + if (g < 0) g = 0; + if (g > 255) g = 255; + if (b < 0) b = 0; + if (b > 255) b = 255; + return ((r << 16) | (g << 8) | b); +} + +static int world_init_from_parsing(t_world *world, t_data *data) +{ + int y; + + world->h = 0; + while (data->map[world->h]) + world->h++; + world->w = ft_strlen(data->map[0]); + + world->grid = malloc(sizeof(char *) * (world->h + 1)); + if (!world->grid) + return (1); + y = 0; + while (y < world->h) + { + world->grid[y] = ft_strdup(data->map[y]); + if (!world->grid[y]) + return (1); + y++; + } + world->grid[world->h] = NULL; + return (0); +} + + +// int main(int ac, char **av) +// { +// t_game g; +// t_data data; + +// if (ac != 2) +// return (printf("Usage: ./cub3d \n"), 1); + +// init_data(&data, av[1]); +// if (parsing(&data)) +// return (printf("Parsing error\n"), 1); +// free_char_array(data.parsing.raw_map); + +// /* init couleurs et textures */ +// g.colors.floor = rgb_to_int(data.texture->floor[0], data.texture->floor[1], data.texture->floor[2]); // ok jai change le fonction rgb_to_int elle attend 3 int le r le g et le b +// g.colors.ceil = rgb_to_int(data.texture->ceiling[0], data.texture->ceiling[1], data.texture->ceiling[2]); +// if (textures_load(&g, +// data.texture->north, data.texture->south, +// data.texture->west, data.texture->east) != 0) +// g.has_tex = 0; + +// /* init map et player */ +// if (world_init_from_parsing(&g.world, &data) != 0) +// return (printf("World init failed\n"), 1); +// double dx = 0, dy = 0; +// if (data.parsing.player[2] == 'N') dy = -1; +// if (data.parsing.player[2] == 'S') dy = 1; +// if (data.parsing.player[2] == 'E') dx = 1; +// if (data.parsing.player[2] == 'W') dx = -1; +// player_init(&g, +// data.parsing.player[0] + 0.5, +// data.parsing.player[1] + 0.5, +// dx, dy); + +// /* window + loop */ +// if (init_window(&g, 1024, 768, "cub3D") != 0) +// return (1); +// setup_hooks(&g); +// mlx_loop(g.gfx.mlx); + +// world_free(&g.world); +// free_data(&data); +// return (0); +// } + +int main(int ac, char **av) +{ + t_game g; + t_data data; + t_texpaths tex; + t_player_init p; + + if (ac != 2) + return (printf("Usage: ./cub3d \n"), 1); + + memset(&g, 0, sizeof(t_game)); //attention memset -> ft_memset ? + + if (init_data(&data, av[1])) + return (1); + if (parsing(&data)) + { + free_textures(data.texture); + free_data(&data); + return (1); + } + + /* init couleurs */ + g.colors.floor = rgb_to_int(data.texture->floor[0], data.texture->floor[1], data.texture->floor[2]); + g.colors.ceil = rgb_to_int(data.texture->ceiling[0], data.texture->ceiling[1], data.texture->ceiling[2]); + + /* init map et player */ + if (world_init_from_parsing(&g.world, &data) != 0) + return (printf("World init failed\n"), 1); + /* Libérer data->map après la duplication vers world->grid */ + free_char_array(data.map); + data.map = NULL; + + p.px = data.parsing.player[0] + 0.5; + p.py = data.parsing.player[1] + 0.5; + p.dx = 0; + p.dy = 0; + if (data.parsing.player[2] == 'S') + p.dy = -1; + if (data.parsing.player[2] == 'N') + p.dy = 1; + if (data.parsing.player[2] == 'E') + p.dx = 1; + if (data.parsing.player[2] == 'W') + p.dx = -1; + player_init(&g, p); + + /* window AVANT textures ! */ + if (init_window(&g, 1024, 768, "cub3D") != 0) + return (1); + + /* MAINTENANT on charge les textures */ + tex.no = data.texture->north; + tex.so = data.texture->south; + tex.we = data.texture->west; + tex.ea = data.texture->east; + + if (textures_load(&g, &tex) != 0) + g.has_tex = 0; + + + /* Passer data à g pour le cleanup */ + g.data = &data; + + setup_hooks(&g); + /* Vider le buffer gnl avant de rentrer dans mlx_loop */ + get_next_line(-2); + mlx_loop(g.gfx.mlx); + + world_free(&g.world); + free_textures(data.texture); + free_data(&data); + + return (0); +} diff --git a/srcs/parsing/check_file.c b/srcs/parsing/check_file.c index 5022033..29bc367 100644 --- a/srcs/parsing/check_file.c +++ b/srcs/parsing/check_file.c @@ -31,6 +31,8 @@ int check_extension(char *map_path) { int len_map_path; + if (!map_path) + return (1); len_map_path = ft_strlen(map_path); if (len_map_path < 4) return (ft_error(ERROR_EXT), 1); diff --git a/srcs/parsing/get_map.c b/srcs/parsing/get_map.c index 343214e..168bc41 100644 --- a/srcs/parsing/get_map.c +++ b/srcs/parsing/get_map.c @@ -6,7 +6,7 @@ /* By: lfirmin +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/08/23 13:29:28 by lfirmin #+# #+# */ -/* Updated: 2025/10/07 10:13:07 by lfirmin ### ########.fr */ +/* Updated: 2025/11/03 09:02:55 by lfirmin ### ########.fr */ /* */ /* ************************************************************************** */ @@ -20,6 +20,8 @@ int get_map(t_data *data) if (nb_line <= 0) return (ft_error(ERROR_EMPTY), 1); data->parsing.raw_map = ft_calloc(nb_line + 1, sizeof(char *)); + if (!data->parsing.raw_map) + return (1); if (put_map_on_array(data)) { free_char_array(data->parsing.raw_map); @@ -60,5 +62,7 @@ char *clean_line(char *raw_line) if (!raw_line) return (NULL); cleaned = ft_strtrim(raw_line, " \t\n\r"); + if (!cleaned) + return (NULL); return (cleaned); } diff --git a/srcs/parsing/get_map_2.c b/srcs/parsing/get_map_2.c index 4a0ffa8..cef8830 100644 --- a/srcs/parsing/get_map_2.c +++ b/srcs/parsing/get_map_2.c @@ -16,6 +16,8 @@ static int process_config_line(char *line, t_data *data, int *j) char *cleaned; cleaned = clean_line(line); + if (!cleaned) + return (-1); if (get_texture_path(cleaned, data->texture, j)) { free(line); diff --git a/srcs/parsing/get_textures.c b/srcs/parsing/get_textures.c index 55b68a5..0b56465 100644 --- a/srcs/parsing/get_textures.c +++ b/srcs/parsing/get_textures.c @@ -11,18 +11,31 @@ /* ************************************************************************** */ #include "cub.h" +static int assign_texture(char *line, char **dest) +{ + char *path; + + path = ft_strtrim(line + 2, " \t\n\r"); + if (!path) + return (ft_error("Memory allocation failed"), -1); + *dest = path; + return (0); +} + int get_texture_path(char *line, t_textures *texture, int *j) { + if (!line) + return (-1); if (check_extension_2(line) && !is_color_line(line)) return (ft_error(ERROR_NOT_XMP), 1); else if (is_texture_line(line) == 1 && j[0]++ == 0) - texture->north = ft_strtrim(line + 2, " \t\n\r"); + return (assign_texture(line, &texture->north)); else if (is_texture_line(line) == 2 && j[1]++ == 0) - texture->south = ft_strtrim(line + 2, " \t\n\r"); + return (assign_texture(line, &texture->south)); else if (is_texture_line(line) == 3 && j[2]++ == 0) - texture->west = ft_strtrim(line + 2, " \t\n\r"); + return (assign_texture(line, &texture->west)); else if (is_texture_line(line) == 4 && j[3]++ == 0) - texture->east = ft_strtrim(line + 2, " \t\n\r"); + return (assign_texture(line, &texture->east)); else if (is_color_line(line) == 1 && j[4]++ == 0) get_rgb_values(line, texture->floor); else if (is_color_line(line) == 2 && j[5]++ == 0) diff --git a/srcs/parsing/line_detect.c b/srcs/parsing/line_detect.c index a76b055..e8c7ab0 100644 --- a/srcs/parsing/line_detect.c +++ b/srcs/parsing/line_detect.c @@ -6,7 +6,7 @@ /* By: lfirmin +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/08/24 11:58:39 by lfirmin #+# #+# */ -/* Updated: 2025/10/08 14:05:47 by lfirmin ### ########.fr */ +/* Updated: 2025/11/03 09:03:03 by lfirmin ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,6 +16,8 @@ int check_extension_2(char *str) { size_t len; + if (!str) + return (1); len = strlen(str); if (len < 4) return (1); @@ -39,7 +41,7 @@ int is_config_line(char *line) || ft_strncmp(trimmed, "EA ", 3) == 0 || ft_strncmp(trimmed, "F ", 2) == 0 || ft_strncmp(trimmed, "C ", 2) == 0) - result = 1; + result = 1; free(trimmed); return (result); } diff --git a/srcs/utils/free.c b/srcs/utils/free.c new file mode 100644 index 0000000..be5ea9c --- /dev/null +++ b/srcs/utils/free.c @@ -0,0 +1,33 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* free.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: lfirmin +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/08/22 18:57:21 by lfirmin #+# #+# */ +/* Updated: 2025/10/08 16:21:46 by lfirmin ### ########.fr */ +/* */ +/* ************************************************************************** */ +#include "cub.h" + +void free_char_array(char **array) +{ + int i; + + if (!array) + return ; + i = 0; + while (array[i]) + free(array[i++]); + free(array); +} + +void free_data(t_data *data) +{ + if (!data) + return ; + if (data->texture) + free(data->texture); + free_char_array(data->map); +} diff --git a/srcs/utils/init.c b/srcs/utils/init.c index 77d21fd..b75c702 100644 --- a/srcs/utils/init.c +++ b/srcs/utils/init.c @@ -20,16 +20,86 @@ int init_data(t_data *data, char *path) return (ft_error(ERROR_INIT_TEX), 1); init_parsing(&data->parsing); init_textures(data->texture); + if (!data->texture) + { + free(data); + return (1); + } data->map = NULL; data->map_path = path; return (0); } -void free_data(t_data *data) +int world_init_from_parsing(t_world *world, t_data *data) { - if (!data) - return ; - if (data->texture) - free(data->texture); - free_char_array(data->map); + int y; + + world->h = 0; + while (data->map[world->h]) + world->h++; + world->w = ft_strlen(data->map[0]); + world->grid = malloc(sizeof(char *) * (world->h + 1)); + if (!world->grid) + return (1); + y = 0; + while (y < world->h) + { + world->grid[y] = ft_strdup(data->map[y]); + if (!world->grid[y]) + return (1); + y++; + } + world->grid[world->h] = NULL; + return (0); +} + +int init_game_data(t_game *g, t_data *data, char *map_file) +{ + ft_memset(g, 0, sizeof(t_game)); + if (init_data(data, map_file)) + return (1); + if (parsing(data)) + { + free_textures(data->texture); + free_data(data); + return (1); + } + g->colors.floor = rgb_to_int(data->texture->floor[0], + data->texture->floor[1], data->texture->floor[2]); + g->colors.ceil = rgb_to_int(data->texture->ceiling[0], + data->texture->ceiling[1], data->texture->ceiling[2]); + if (world_init_from_parsing(&g->world, data) != 0) + return (printf("World init failed\n"), 1); + free_char_array(data->map); + data->map = NULL; + return (0); +} + +void init_player_direction(t_player_init *p, char direction) +{ + p->dx = 0; + p->dy = 0; + if (direction == 'S') + p->dy = -1; + else if (direction == 'N') + p->dy = 1; + else if (direction == 'E') + p->dx = 1; + else if (direction == 'W') + p->dx = -1; +} + +int init_mlx_and_textures(t_game *g, t_data *data) +{ + t_texpaths tex; + + if (init_window(g, 1024, 768, "cub3D") != 0) + return (1); + tex.no = data->texture->north; + tex.so = data->texture->south; + tex.we = data->texture->west; + tex.ea = data->texture->east; + if (textures_load(g, &tex) != 0) + g->has_tex = 0; + return (0); } diff --git a/srcs/utils/utils.c b/srcs/utils/utils.c index 1ec6fcd..5ec926d 100644 --- a/srcs/utils/utils.c +++ b/srcs/utils/utils.c @@ -24,18 +24,6 @@ void ft_error(char *message) write(2, "\n", 1); } -void free_char_array(char **array) -{ - int i; - - if (!array) - return ; - i = 0; - while (array[i]) - free(array[i++]); - free(array); -} - int ft_arrlen(char **arr) { int i; @@ -68,3 +56,20 @@ int ft_strlen_2d(char **str) ++i; return (i); } + +int rgb_to_int(int r, int g, int b) +{ + if (r < 0) + r = 0; + if (r > 255) + r = 255; + if (g < 0) + g = 0; + if (g > 255) + g = 255; + if (b < 0) + b = 0; + if (b > 255) + b = 255; + return ((r << 16) | (g << 8) | b); +}