/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* cub3d.h :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: ezafra-r +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/02/08 18:17:00 by ezafra-r #+# #+# */ /* Updated: 2024/02/08 18:43:52 by ezafra-r ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef CUB3D_H # define CUB3D_H /*═════════════════════════════ [ LIBS ] ═══════════════════════════════════*/ // personal libs # include "../lib/libft/inc/libft.h" # include "../lib/libmlx/include/MLX42/MLX42.h" // global libs # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include /*═══════════════════════════ [ MACROS ] ═══════════════════════════════════*/ // MLX - GAME # define S_W 1900 // screen width # define S_H 1000 // screen height # define WALL_SIZE 30 // wall size # define FOV 60 // field of view # define ROTATION_SPEED 0.045 // rotation speed # define PLAYER_SPEED 4 // player speed // ERROR # define ERR_INV_COP "Error: invalid argument\n" # define ERR_INV_FILE "Error: invalid file\n" # define ERR_EMPTY_FILE "Error: empty file\n" # define ERR_MAP_INV "Error: invalid map element\n" # define ERR_MAP_EMPTY "Error: empty ligne in the map\n" # define ERR_MAP_DUP "Error: duplicate map element\n" # define ERR_MAP_RGB "Error: invalid color map [RGB]\n" /*══════════════════════════ [ STRUCTS ] ═══════════════════════════════════*/ typedef struct s_tex { mlx_texture_t *no; mlx_texture_t *so; mlx_texture_t *we; mlx_texture_t *ea; } t_tex; typedef struct s_turelist { char *name; char *value; struct s_turelist *next; } t_turelist; typedef struct s_player { int plyr_x; // player x position in pixels int plyr_y; // player y position in pixels double angle; // player angle float fov_rd; // field of view in radians int rot; // rotation flag int l_r; // left right flag int u_d; // up down flag } t_player; typedef struct s_ray { int index; double ray_ngl; double horiz_x; double horiz_y; double vert_x; double vert_y; double distance; int flag; } t_ray; typedef struct s_data { int p_x; // player x position in the map int p_y; // player y position in the map int w_map; // map width int h_map; // map height int fd; char *line; char *ture; char **ture2d; char *map; char **map2d; char **sq_map; char **cc; char **ff; t_turelist *t_list; } t_data; typedef struct s_mlx { mlx_image_t *img; // the image mlx_t *mlx_ptr; // the mlx pointer t_ray *ray; // the ray structure t_data *dt; // the data structure t_player *ply; // the player structure t_tex *tex; t_turelist *l_ture; } t_mlx; /*═════════════════════════ [ FUNCTIONS ] ══════════════════════════════════*/ /*-------------------------- [ parsing ] -----------------------------------*/ // p_frees.c void freetl(char *ture, char *line, int fd); void free_map(t_data *m); void free_m(t_mlx *mlx); void freelist(t_turelist **head); // p_lst_ture.c int get_index(char *line, int i); t_turelist *new_texture(char *line); void lst_back_ture(t_turelist **l_ture, t_turelist *new); int lst_ture(t_data *m, t_turelist **l_ture); // p_read_map_utils.c int check_tures_space_tab(char **ture2d, int count); int parse_rgb(char **ture2d); int check_dup(t_data *m); int check_first_last_line(char **map); int surounded_by_one(char **map); // p_read_map.c int is_surrounded(char *line); int is_validmap(char *line, int *flag); char *getmap(t_data *m); int read_map_(t_data *m, int count); void process_map(t_data *map, int *count); // p_texture_utils.c int is_valid_texture(char *line); int count_comma(char *rgb); int check_pos_cf(char *line); int line_arond_one(char *line); char *getlastline(char **map); // p_texture.c int check_color_values(char **rgb); void ft_process_rgb_color(t_turelist *tmp, t_data *m); int color_ture(t_data *m, t_turelist *l_ture); int check_color_textures(char *line); int check_count_textures(t_data *m, int count); // p_valid_map.c int h_map(char **map); int v_map(char **map); char *fixline(char *line, int maxlen); int getsize_line(char **map); int valid_map(t_data *m); // parsing.c int read_map(char *av, t_data *data, int *count); void get_x_y_player(t_data *m); int parsing(int ac, char **av, t_data *data); int check_extension_map(char *fname); /*------------------------ [ execution ] -----------------------------------*/ // execfree.c void ft_delete_tex(t_tex *tex); void ft_exit(t_mlx *mlx); // mouvement.c void rotate_player(t_mlx *mlx, int i); void move_player(t_mlx *mlx, double move_x, double move_y); void cub_hook(t_mlx *mlx, double move_x, double move_y); void ft_reset_move(mlx_key_data_t keydata, t_mlx *mlx); void key_press(mlx_key_data_t keydata, void *ml); // execution.c void get_angle(t_mlx *mlx); void drow_map_pixel(void *mlxl); int check_load_ture(t_turelist *list); int load_texture(t_tex *tex, t_turelist *l_ture); int execution(t_data *dt); // raycasting.c int inter_check(float angle, float *inter, float *step, int is_horizon); int wall_hit(float x, float y, t_mlx *mlx); float get_h_inter(t_mlx *mlx, float angl); float get_v_inter(t_mlx *mlx, float angl); void cast_rays(t_mlx *mlx); // render2.c int get_rgba(int r, int g, int b, int a); int reverse_bytes(int c); void my_mlx_pixel_put(t_mlx *mlx, int x, int y, int color); float nor_angle(float angle); int unit_circle(float angle, char c); // render.c double get_x_o(mlx_texture_t *texture, t_mlx *mlx); void draw_floor_ceiling(t_mlx *mlx, int ray, int t_pix, int b_pix); void draw_wall(t_mlx *mlx, int t_pix, int b_pix, double wall_h); void render_wall(t_mlx *mlx, int ray); #endif # **************************************************************************** # # # # ::: :::::::: # # e_frees.c :+: :+: :+: # # +:+ +:+ +:+ # # By: aortigos no) mlx_delete_texture(tex->no); if (tex->so) mlx_delete_texture(tex->so); if (tex->we) mlx_delete_texture(tex->we); if (tex->ea) mlx_delete_texture(tex->ea); } void ft_exit(t_mlx *mlx) { mlx_delete_image(mlx->mlx_ptr, mlx->img); mlx_close_window(mlx->mlx_ptr); freelist(&mlx->dt->t_list); free_map(mlx->dt); ft_delete_tex(mlx->tex); ft_memfree(mlx->tex); ft_memfree(mlx->ply); ft_memfree(mlx->ray); mlx_terminate(mlx->mlx_ptr); ft_putstr_fd("END GAME\n", 1); exit(0); } /* ************************************************************************** */ /* e_mouvement.c :+: :+: :+: */ /* ************************************************************************** */ #include "cub3d.h" void rotate_player(t_mlx *mlx, int i) { if (i == 1) { mlx->ply->angle += ROTATION_SPEED; if (mlx->ply->angle > 2 * M_PI) mlx->ply->angle -= 2 * M_PI; } else { mlx->ply->angle -= ROTATION_SPEED; if (mlx->ply->angle < 0) mlx->ply->angle += 2 * M_PI; } } void move_player(t_mlx *mlx, double move_x, double move_y) { int map_grid_y; int map_grid_x; int new_x; int new_y; new_x = roundf(mlx->ply->plyr_x + move_x); new_y = roundf(mlx->ply->plyr_y + move_y); map_grid_x = (new_x / WALL_SIZE); map_grid_y = (new_y / WALL_SIZE); if (mlx->dt->sq_map[map_grid_y][map_grid_x] != '1' && (mlx->dt->sq_map[map_grid_y][mlx->ply->plyr_x / WALL_SIZE] != '1' && mlx->dt->sq_map[mlx->ply->plyr_y / WALL_SIZE][map_grid_x] != '1')) { mlx->ply->plyr_x = new_x; mlx->ply->plyr_y = new_y; } } void cub_hook(t_mlx *mlx, double move_x, double move_y) { if (mlx->ply->rot == 1) rotate_player(mlx, 1); if (mlx->ply->rot == -1) rotate_player(mlx, 0); if (mlx->ply->l_r == 1) { move_x = -sin(mlx->ply->angle) * PLAYER_SPEED; move_y = cos(mlx->ply->angle) * PLAYER_SPEED; } if (mlx->ply->l_r == -1) { move_x = sin(mlx->ply->angle) * PLAYER_SPEED; move_y = -cos(mlx->ply->angle) * PLAYER_SPEED; } if (mlx->ply->u_d == 1) { move_x = cos(mlx->ply->angle) * PLAYER_SPEED; move_y = sin(mlx->ply->angle) * PLAYER_SPEED; } if (mlx->ply->u_d == -1) { move_x = -cos(mlx->ply->angle) * PLAYER_SPEED; move_y = -sin(mlx->ply->angle) * PLAYER_SPEED; } move_player(mlx, move_x, move_y); } void ft_reset_move(mlx_key_data_t keydata, t_mlx *mlx) { if (keydata.key == MLX_KEY_D && (keydata.action == MLX_RELEASE)) mlx->ply->l_r = 0; else if (keydata.key == MLX_KEY_A && (keydata.action == MLX_RELEASE)) mlx->ply->l_r = 0; else if (keydata.key == MLX_KEY_S && (keydata.action == MLX_RELEASE)) mlx->ply->u_d = 0; else if (keydata.key == MLX_KEY_W && (keydata.action == MLX_RELEASE)) mlx->ply->u_d = 0; else if (keydata.key == MLX_KEY_LEFT && keydata.action == MLX_RELEASE) mlx->ply->rot = 0; else if (keydata.key == MLX_KEY_RIGHT && keydata.action == MLX_RELEASE) mlx->ply->rot = 0; } void key_press(mlx_key_data_t keydata, void *ml) { t_mlx *mlx; mlx = ml; if (keydata.key == MLX_KEY_ESCAPE && (keydata.action == MLX_PRESS || keydata.action == MLX_REPEAT)) { ft_exit(mlx); } else if (keydata.key == MLX_KEY_A && (keydata.action == MLX_PRESS)) mlx->ply->l_r = -1; else if (keydata.key == MLX_KEY_D && (keydata.action == MLX_PRESS)) mlx->ply->l_r = 1; else if (keydata.key == MLX_KEY_S && (keydata.action == MLX_PRESS)) mlx->ply->u_d = -1; else if (keydata.key == MLX_KEY_W && keydata.action == MLX_PRESS) mlx->ply->u_d = 1; else if (keydata.key == MLX_KEY_LEFT && keydata.action == MLX_PRESS) mlx->ply->rot = -1; else if (keydata.key == MLX_KEY_RIGHT && keydata.action == MLX_PRESS) mlx->ply->rot = 1; ft_reset_move(keydata, mlx); } /* ************************************************************************** */ /* e_raycasting.c :+: :+: :+: */ /* ************************************************************************** */ #include "cub3d.h" int inter_check(float angle, float *inter, float *step, int is_horizon) { if (is_horizon) { if (angle > 0 && angle < M_PI) { *inter += WALL_SIZE; return (-1); } *step *= -1; } else { if (!(angle > M_PI / 2 && angle < 3 * M_PI / 2)) { *inter += WALL_SIZE; return (-1); } *step *= -1; } return (1); } int wall_hit(float x, float y, t_mlx *mlx) { int x_m; int y_m; if (x < 0 || y < 0) return (0); x_m = floor(x / WALL_SIZE); y_m = floor(y / WALL_SIZE); if ((y_m >= mlx->dt->h_map || x_m >= mlx->dt->w_map)) return (0); if (mlx->dt->map2d[y_m] && x_m <= (int)ft_strlen(mlx->dt->map2d[y_m])) if (mlx->dt->map2d[y_m][x_m] == '1') return (0); return (1); } float get_h_inter(t_mlx *mlx, float angl) { float h_x; float h_y; float x_step; float y_step; int pixel; y_step = WALL_SIZE; x_step = WALL_SIZE / tan(angl); h_y = floor(mlx->ply->plyr_y / WALL_SIZE) * WALL_SIZE; pixel = inter_check(angl, &h_y, &y_step, 1); h_x = mlx->ply->plyr_x + (h_y - mlx->ply->plyr_y) / tan(angl); if ((unit_circle(angl, 'y') && x_step > 0) || (!unit_circle(angl, 'y') && x_step < 0)) x_step *= -1; while (wall_hit(h_x, h_y - pixel, mlx)) { h_x += x_step; h_y += y_step; } mlx->ray->horiz_x = h_x; mlx->ray->horiz_y = h_y; return (sqrt(pow(h_x - mlx->ply->plyr_x, 2) + pow(h_y - mlx->ply->plyr_y, 2))); } float get_v_inter(t_mlx *mlx, float angl) { float v_x; float v_y; float x_step; float y_step; int pixel; x_step = WALL_SIZE; y_step = WALL_SIZE * tan(angl); v_x = floor(mlx->ply->plyr_x / WALL_SIZE) * WALL_SIZE; pixel = inter_check(angl, &v_x, &x_step, 0); v_y = mlx->ply->plyr_y + (v_x - mlx->ply->plyr_x) * tan(angl); if ((unit_circle(angl, 'x') && y_step < 0) || (!unit_circle(angl, 'x') && y_step > 0)) y_step *= -1; while (wall_hit(v_x - pixel, v_y, mlx)) { v_x += x_step; v_y += y_step; } mlx->ray->vert_x = v_x; mlx->ray->vert_y = v_y; return (sqrt(pow(v_x - mlx->ply->plyr_x, 2) + pow(v_y - mlx->ply->plyr_y, 2))); } void cast_rays(t_mlx *mlx) { double h_inter; double v_inter; int ray; ray = 0; mlx->ray->ray_ngl = mlx->ply->angle - (mlx->ply->fov_rd / 2); while (ray < S_W) { mlx->ray->flag = 0; h_inter = get_h_inter(mlx, nor_angle(mlx->ray->ray_ngl)); v_inter = get_v_inter(mlx, nor_angle(mlx->ray->ray_ngl)); if (v_inter <= h_inter) mlx->ray->distance = v_inter; else { mlx->ray->distance = h_inter; mlx->ray->flag = 1; } render_wall(mlx, ray); ray++; mlx->ray->ray_ngl += (mlx->ply->fov_rd / S_W); } } /* ************************************************************************** */ /* e_render.c :+: :+: :+: */ /* ************************************************************************** */ #include "cub3d.h" void draw_floor_ceiling(t_mlx *mlx, int ray, int t_pix, int b_pix) { int i; int c; i = b_pix; c = get_rgba(ft_atoi(mlx->dt->ff[0]), ft_atoi(mlx->dt->ff[1]), ft_atoi(mlx->dt->ff[2]), 255); while (i < S_H) my_mlx_pixel_put(mlx, ray, i++, c); c = get_rgba(ft_atoi(mlx->dt->cc[0]), ft_atoi(mlx->dt->cc[1]), ft_atoi(mlx->dt->cc[2]), 255); i = 0; while (i < t_pix) my_mlx_pixel_put(mlx, ray, i++, c); } mlx_texture_t *get_texture(t_mlx *mlx, int flag) { mlx->ray->ray_ngl = nor_angle(mlx->ray->ray_ngl); if (flag == 0) { if (mlx->ray->ray_ngl > M_PI / 2 && mlx->ray->ray_ngl < 3 * (M_PI / 2)) return (mlx->tex->ea); else return (mlx->tex->we); } else { if (mlx->ray->ray_ngl > 0 && mlx->ray->ray_ngl < M_PI) return (mlx->tex->so); else return (mlx->tex->no); } } double get_x_o(mlx_texture_t *texture, t_mlx *mlx) { double x_o; if (mlx->ray->flag == 1) x_o = (int)fmodf((mlx->ray->horiz_x * (texture->width / WALL_SIZE)), texture->width); else x_o = (int)fmodf((mlx->ray->vert_y * (texture->width / WALL_SIZE)), texture->width); return (x_o); } void draw_wall(t_mlx *mlx, int t_pix, int b_pix, double wall_h) { double x_o; double y_o; mlx_texture_t *texture; uint32_t *arr; double factor; texture = get_texture(mlx, mlx->ray->flag); arr = (uint32_t *)texture->pixels; factor = (double)texture->height / wall_h; x_o = get_x_o(texture, mlx); y_o = (t_pix - (S_H / 2) + (wall_h / 2)) * factor; if (y_o < 0) y_o = 0; while (t_pix < b_pix) { my_mlx_pixel_put(mlx, mlx->ray->index, t_pix, reverse_bytes(arr[(int)y_o * texture->width + (int)x_o])); y_o += factor; t_pix++; } } void render_wall(t_mlx *mlx, int ray) { double wall_h; double b_pix; double t_pix; mlx->ray->distance *= cos(nor_angle(mlx->ray->ray_ngl - mlx->ply->angle)); wall_h = (WALL_SIZE / mlx->ray->distance) * ((S_W / 2) / tan(mlx->ply->fov_rd / 2)); b_pix = (S_H / 2) + (wall_h / 2); t_pix = (S_H / 2) - (wall_h / 2); if (b_pix > S_H) b_pix = S_H; if (t_pix < 0) t_pix = 0; mlx->ray->index = ray; draw_wall(mlx, t_pix, b_pix, wall_h); draw_floor_ceiling(mlx, ray, t_pix, b_pix); } /* ************************************************************************** */ /* e_render2.c :+: :+: :+: */ /* ************************************************************************** */ #include "cub3d.h" int get_rgba(int r, int g, int b, int a) { return (r << 24 | g << 16 | b << 8 | a << 0); } int reverse_bytes(int c) { unsigned int b; b = 0; b |= (c & 0xFF) << 24; b |= (c & 0xFF00) << 8; b |= (c & 0xFF0000) >> 8; b |= (c & 0xFF000000) >> 24; return (b); } void my_mlx_pixel_put(t_mlx *mlx, int x, int y, int color) { if (x < 0) return ; else if (x >= S_W) return ; if (y < 0) return ; else if (y >= S_H) return ; mlx_put_pixel(mlx->img, x, y, color); } float nor_angle(float angle) { if (angle < 0) angle += (2 * M_PI); if (angle > (2 * M_PI)) angle -= (2 * M_PI); return (angle); } int unit_circle(float angle, char c) { if (c == 'x') { if (angle > 0 && angle < M_PI) return (1); } else if (c == 'y') { if (angle > (M_PI / 2) && angle < (3 * M_PI) / 2) return (1); } return (0); } /* ************************************************************************** */ /* execution.c :+: :+: :+: */ /* ************************************************************************** */ #include "cub3d.h" void drow_map_pixel(void *mlxl) { t_mlx *mlx; mlx = mlxl; mlx_delete_image(mlx->mlx_ptr, mlx->img); mlx->img = mlx_new_image(mlx->mlx_ptr, S_W, S_H); cub_hook(mlx, 0, 0); cast_rays(mlx); mlx_image_to_window(mlx->mlx_ptr, mlx->img, 0, 0); } int check_load_ture(t_turelist *list) { t_turelist *tmp; mlx_texture_t *texture; tmp = list; while (tmp) { if (!ft_strncmp(tmp->name, "NO", 2) || !ft_strncmp(tmp->name, "SO", 2) || !ft_strncmp(tmp->name, "WE", 2) || !ft_strncmp(tmp->name, "EA", 2)) { texture = mlx_load_png(tmp->value); if (!texture) return (0); mlx_delete_texture(texture); } tmp = tmp->next; } return (1); } int load_texture(t_tex *tex, t_turelist *l_ture) { t_turelist *tmp; tmp = l_ture; if (!check_load_ture(l_ture)) return (0); while (tmp) { if (!ft_strncmp(tmp->name, "NO", 2)) tex->no = mlx_load_png(tmp->value); else if (!ft_strncmp(tmp->name, "SO", 2)) tex->so = mlx_load_png(tmp->value); else if (!ft_strncmp(tmp->name, "WE", 2)) tex->we = mlx_load_png(tmp->value); else if (!ft_strncmp(tmp->name, "EA", 2)) tex->ea = mlx_load_png(tmp->value); tmp = tmp->next; } return (1); } void get_angle(t_mlx *mlx) { char c; c = mlx->dt->sq_map[mlx->dt->p_y][mlx->dt->p_x]; if (c == 'N') mlx->ply->angle = 3 * M_PI / 2; if (c == 'S') mlx->ply->angle = M_PI / 2; if (c == 'E') mlx->ply->angle = 0; if (c == 'W') mlx->ply->angle = M_PI; mlx->ply->plyr_x = (mlx->dt->p_x * WALL_SIZE) + WALL_SIZE / 2; mlx->ply->plyr_y = (mlx->dt->p_y * WALL_SIZE) + WALL_SIZE / 2; mlx->ply->fov_rd = (FOV * M_PI / 180); } int execution(t_data *dt) { t_mlx mlx; if (S_H > 1440 || S_W > 2560 || FOV >= 180 || FOV <= 0) return (freelist(&dt->t_list), free_map(dt), 0); mlx.ply = (t_player *)ft_calloc(sizeof(t_player), 1); mlx.ray = (t_ray *)ft_calloc(sizeof(t_ray), 1); mlx.tex = (t_tex *)ft_calloc(sizeof(t_tex), 1); mlx.dt = dt; mlx.mlx_ptr = mlx_init(S_W, S_H, "cub3D", false); if (!mlx.mlx_ptr) return (ft_exit(&mlx), 0); if (!load_texture(mlx.tex, dt->t_list)) return (ft_exit(&mlx), 0); get_angle(&mlx); mlx_key_hook(mlx.mlx_ptr, &key_press, &mlx); mlx_loop_hook(mlx.mlx_ptr, &drow_map_pixel, &mlx); mlx_loop(mlx.mlx_ptr); ft_exit(&mlx); return (0); } /* ************************************************************************** */ /* main.c :+: :+: :+: */ /* ************************************************************************** */ #include "cub3d.h" int main(int ac, char **av) { t_data dt; if (!parsing(ac, av, &dt)) return (1); execution(&dt); return (0); } /* ************************************************************************** */ /* p_frees.c :+: :+: :+: */ /* ************************************************************************** */ #include "cub3d.h" void freetl(char *ture, char *line, int fd) { if (ture) ft_memfree(ture); if (line) ft_memfree(line); if (fd >= 0) close(fd); } void free_map(t_data *m) { free2d(m->sq_map); free2d(m->map2d); free2d(m->ture2d); if (m->ff) free2d(m->ff); if (m->cc) free2d(m->cc); } void free_m(t_mlx *mlx) { if (mlx->dt->sq_map) free2d(mlx->dt->sq_map); if (mlx->dt->map2d) free2d(mlx->dt->map2d); if (mlx->dt->ture2d) free2d(mlx->dt->ture2d); if (mlx->dt->ff) free2d(mlx->dt->ff); if (mlx->dt->cc) free2d(mlx->dt->cc); } void freelist(t_turelist **head) { t_turelist *tmp; tmp = *head; while (tmp) { *head = tmp->next; ft_memfree(tmp->name); ft_memfree(tmp->value); ft_memfree(tmp); tmp = *head; } ft_memfree(*head); } /* ************************************************************************** */ /* p_lst_ture.c :+: :+: :+: */ /* ************************************************************************** */ #include "cub3d.h" int get_index(char *line, int i) { while (ft_isspace(line[i])) i++; return (i); } t_turelist *new_texture(char *line) { t_turelist *list; list = (t_turelist *)ft_calloc(sizeof(t_turelist), 1); if (!list) return (NULL); while (ft_isspace(*line)) line++; if ((!ft_strncmp(line, "NO", 2) || !ft_strncmp(line, "SO", 2) || !ft_strncmp(line, "WE", 2) || !ft_strncmp(line, "EA", 2))) { list->name = ft_substr(line, 0, 2); list->value = ft_substr(line, get_index(line, 2), ft_strlen(line)); } else if ((!ft_strncmp(line, "F", 1) || !ft_strncmp(line, "C", 1))) { list->name = ft_substr(line, 0, 1); list->value = ft_substr(line, get_index(line, 1), ft_strlen(line)); } list->next = NULL; return (list); } void lst_back_ture(t_turelist **l_ture, t_turelist *new) { t_turelist *tmp; if (!*l_ture) { (*l_ture) = new; return ; } tmp = *l_ture; while (tmp->next) tmp = tmp->next; tmp->next = new; } int lst_ture(t_data *m, t_turelist **l_ture) { int i; t_turelist *tmp; i = 0; while (m->ture2d[i]) { tmp = new_texture(m->ture2d[i++]); if (!tmp) return (0); lst_back_ture(l_ture, tmp); } return (1); } /* ************************************************************************** */ /* p_read_map.c :+: :+: :+: */ /* ************************************************************************** */ #include "cub3d.h" int is_surrounded(char *line) { while (ft_isspace(*line)) line++; return (*line == '1' && line[ft_strlen(line) - 1] == '1'); } int is_validmap(char *line, int *flag) { int i; i = -1; while (line[++i]) { if ((line[i] != '1' && line[i] != 32 && line[i] != '0' && line[i] != '\n') && !(line[i] == 'W' || line[i] == 'E' || line[i] == 'N' || line[i] == 'S')) return (0); else if (line[i] == 'W' || line[i] == 'E' || line[i] == 'N' || line[i] == 'S') (*flag)++; } return (1); } char *getmap(t_data *map) { char *temp; map->map = ft_strdup(""); while (map->line) { if (map->line[0] == '\n') return (ft_putstr_fd(ERR_MAP_EMPTY, 2), freetl(map->map, map->line, -1), NULL); temp = ft_strjoin(map->map, map->line); ft_memfree(map->map); ft_memfree(map->line); map->map = ft_strdup(temp); ft_memfree(temp); map->line = get_next_line(map->fd); } return (map->map); } int read_map_(t_data *map, int count) { map->map = getmap(map); if (!map->map) return (0); map->map2d = ft_split(map->map, '\n'); if (!map->map2d) return (ft_memfree(map->map), 0); ft_memfree(map->map); if (!check_tures_space_tab(map->ture2d, count) || !parse_rgb(map->ture2d) || !check_dup(map) || !check_first_last_line(map->map2d) || !surounded_by_one(map->map2d)) return (free2d(map->map2d), 0); return (1); } void process_map(t_data *map, int *count) { char *temp_ture; while (map->line && map->line[0] != '1' && map->line[0] != 32) { if (check_color_textures(map->line)) { temp_ture = ft_strjoin(map->ture, map->line); ft_memfree(map->ture); map->ture = strdup(temp_ture); ft_memfree(temp_ture); (*count)++; } ft_memfree(map->line); map->line = get_next_line(map->fd); } } /* ************************************************************************** */ /* p_read_map_utils.c :+: :+: :+: */ /* ************************************************************************** */ #include "cub3d.h" int check_tures_space_tab(char **ture2d, int count) { int i; i = -1; if (count != 6) return (0); while (++i < count) if (!is_valid_texture(ture2d[i])) return (ft_putstr_fd("texture mal\n", 2), 0); return (1); } int parse_rgb(char **ture2d) { int i; char *ptr; i = 0; while (ture2d[i]) { ptr = ture2d[i]; while (ft_isspace(*ptr)) ptr++; if (ptr[0] == 'F' || ptr[0] == 'C') if (count_comma(ptr) != 2 || !check_pos_cf(ptr)) return (ft_putstr_fd("color mal\n", 2), 0); i++; } return (1); } int check_dup(t_data *m) { int i; int j; i = 0; while (m->ture2d[i]) { j = i + 1; while (m->ture2d[j]) { if (!ft_strncmp(m->ture2d[i], m->ture2d[j], 2)) return (ft_putstr_fd(ERR_MAP_DUP, 2), 0); j++; } i++; } return (1); } int check_first_last_line(char **map) { if (!map[0]) return (ft_putstr_fd(ERR_MAP_INV, 2), 0); if (!line_arond_one(map[0]) || !line_arond_one(map[ft_arraylen(map) - 1])) return (ft_putstr_fd("one Y\n", 2), 0); return (1); } int surounded_by_one(char **map) { int i; int flag; flag = 0; i = -1; while (map[++i]) if (!is_surrounded(map[i]) || !is_validmap(map[i], &flag) || flag > 1) return (ft_putstr_fd("one X\n", 2), 0); if (flag == 0) return (ft_putstr_fd("no position map\n", 2), 0); return (1); } /* ************************************************************************** */ /* p_textures.c :+: :+: :+: */ /* ************************************************************************** */ #include "cub3d.h" int check_color_values(char **rgb) { int i; i = -1; while (rgb[++i]) if (ft_atoi(rgb[i]) > 255 || ft_atoi(rgb[i]) < 0) return (free2d(rgb), 0); return (free2d(rgb), 1); } void ft_process_rgb_color(t_turelist *tmp, t_data *m) { if (!ft_strncmp(tmp->name, "F", 2)) m->ff = ft_split(tmp->value, ','); else if (!ft_strncmp(tmp->name, "C", 2)) m->cc = ft_split(tmp->value, ','); return ; } int color_ture(t_data *m, t_turelist *l_ture) { t_turelist *tmp; m->cc = NULL; m->ff = NULL; tmp = l_ture; while (tmp) { if (!ft_strncmp(tmp->name, "F", 1) || !ft_strncmp(tmp->name, "C", 1)) { if (!check_color_values(ft_split(tmp->value, ','))) return (ft_putstr_fd(ERR_MAP_RGB, 2), 0); ft_process_rgb_color(tmp, m); } tmp = tmp->next; } return (1); } int check_color_textures(char *line) { while (ft_isspace(*line)) line++; return ((!ft_strncmp(line, "EA", 2) || !ft_strncmp(line, "NO", 2) || !ft_strncmp(line, "SO", 2) || !ft_strncmp(line, "WE", 2)) || (!ft_strncmp(line, "F", 1) || !ft_strncmp(line, "C", 1))); } int check_count_textures(t_data *m, int count) { (void)m; if (count != 6) return (ft_putstr_fd(ERR_MAP_INV, 2), 0); return (1); } /* ************************************************************************** */ /* p_textures_utils.c :+: :+: :+: */ /* ************************************************************************** */ #include "cub3d.h" int is_valid_texture(char *line) { while (ft_isspace(*line)) line++; if ((!ft_strncmp(line, "NO", 2) || !ft_strncmp(line, "SO", 2) || !ft_strncmp(line, "WE", 2) || !ft_strncmp(line, "EA", 2)) && ft_isspace(line[2])) return (1); else if ((!ft_strncmp(line, "F", 1) || !ft_strncmp(line, "C", 1)) && ft_isspace(line[1])) return (1); return (0); } int count_comma(char *rgb) { int i; int count; i = 0; count = 0; while (rgb[i]) if (rgb[i++] == ',') count++; return (count); } int check_pos_cf(char *l) { int i; int flag; flag = 0; i = 0; while (ft_isspace(*l) || *l == 'C' || *l == 'F') { if (*l == 'C' || *l == 'F') flag++; l++; } if (flag != 1) return (0); if (!ft_isdigit(l[i]) || !ft_isdigit(l[(ft_strlen(l) - 1)])) return (0); while (l[i]) { if ((!ft_isdigit(l[i]) && l[i] != ',') || (l[i] == ',' && l[i + 1] && l[i + 1] == ',')) return (0); i++; } return (1); } int line_arond_one(char *line) { int i; i = -1; while (line[++i]) if (line[i] != '1' && line[i] != 32) return (0); return (1); } char *getlastline(char **map) { int i; i = 0; while (map[i + 1]) i++; return (map[i]); } /* ************************************************************************** */ /* p_valid_map.c :+: :+: :+: */ /* ************************************************************************** */ #include "cub3d.h" int h_map(char **map) { int i; int j; i = 0; while (map[i]) { j = 0; while (map[i][j]) { if (map[i][j] != '1' && map[i][j] != ' ') if (map[i][j - 1] == ' ' || map[i][j + 1] == ' ') return (ft_putstr_fd(ERR_MAP_INV, 2), 0); j++; } i++; } return (1); } int v_map(char **map) { int i; int j; i = 0; while (map[i]) { j = 0; while (map[i][j]) { if (map[i][j] != '1' && map[i][j] != ' ') if (map[i - 1][j] == ' ' || map[i + 1][j] == ' ') return (ft_putstr_fd(ERR_MAP_INV, 2), 0); j++; } i++; } return (1); } char *fixline(char *line, int maxlen) { char *new; int i; i = 0; new = ft_calloc(sizeof(char), (maxlen + 1)); if (!new) return (NULL); while (line[i]) { new[i] = line[i]; i++; } while (i < maxlen) { new[i] = ' '; i++; } return (new); } int getsize_line(char **map) { int i; int max; i = -1; max = ft_strlen(map[0]); while (map[++i]) if ((int)ft_strlen(map[i]) > max) max = ft_strlen(map[i]); return (max); } int valid_map(t_data *m) { int i; int maxlen; maxlen = getsize_line(m->map2d); m->sq_map = ft_calloc(sizeof(char *), (ft_arraylen(m->map2d) + 1)); if (!m->sq_map) return (0); i = -1; while (m->map2d[++i]) { if (maxlen == (int)ft_strlen(m->map2d[i])) m->sq_map[i] = ft_strdup(m->map2d[i]); else m->sq_map[i] = fixline(m->map2d[i], maxlen); } m->h_map = ft_arraylen(m->sq_map); m->w_map = ft_strlen(m->sq_map[0]); if (!h_map(m->sq_map) || !v_map(m->sq_map)) return (free2d(m->sq_map), free2d(m->map2d), free2d(m->ture2d), 0); return (1); } /* ************************************************************************** */ /* parsing.c :+: :+: :+: */ /* ************************************************************************** */ #include "cub3d.h" int read_map(char *av, t_data *map, int *count) { map->fd = open(av, O_RDONLY); if (map->fd == -1) return (ft_putstr_fd(ERR_INV_FILE, 2), 0); map->line = get_next_line(map->fd); if (map->line == NULL) return (ft_putstr_fd(ERR_EMPTY_FILE, 2), 0); map->ture = ft_strdup(""); process_map(map, count); if (!check_count_textures(map, *count)) return (freetl(map->ture, map->line, map->fd), 0); map->ture2d = ft_split(map->ture, '\n'); if (!map->ture2d) return (freetl(map->ture, map->line, map->fd), 0); if (!read_map_(map, *count)) return (freetl(map->ture, map->line, map->fd), free2d(map->ture2d), 0); return (freetl(map->ture, map->line, map->fd), 1); } void get_x_y_player(t_data *m) { int i; int j; i = 0; while (m->sq_map[i]) { j = 0; while (m->sq_map[i][j]) { if (m->sq_map[i][j] == 'N' || m->sq_map[i][j] == 'S' || m->sq_map[i][j] == 'W' || m->sq_map[i][j] == 'E') { m->p_x = j; m->p_y = i; return ; } j++; } i++; } } int check_extension_map(char *file_name) { char *dot; dot = ft_strrchr(file_name, '.'); return (dot && !ft_strcmp(dot, ".cub")); } int parsing(int ac, char **av, t_data *data) { int count; if (ac != 2 || !check_extension_map(av[1])) return (ft_putstr_fd(ERR_INV_COP, 2), 0); count = 0; if (!read_map(av[1], data, &count)) return (0); if (!valid_map(data)) return (0); data->t_list = NULL; if (!lst_ture(data, &data->t_list)) return (free_map(data), freelist(&data->t_list), 0); if (!color_ture(data, data->t_list)) return (free_map(data), freelist(&data->t_list), 0); get_x_y_player(data); return (1); }