commit 06267858e8454e270b7a9270ef680ba11e0f4239 Author: aortigos Date: Fri Nov 14 15:07:40 2025 +0100 Hello world diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2023d23 --- /dev/null +++ b/Makefile @@ -0,0 +1,30 @@ +NAME := cub3d +CFLAGS := -Wextra -Wall -Werror -Wunreachable-code -Ofast +LIBMLX := ./lib/mlx + +HEADERS := -I ./include -I $(LIBMLX)/include +LIBS := $(LIBMLX)/build/libmlx42.a -ldl -lglfw -pthread -lm +SRCS := $(shell find ./src -iname "*.c") +OBJS := ${SRCS:.c=.o} + +all: libmlx $(NAME) + +libmlx: + @cmake $(LIBMLX) -B $(LIBMLX)/build && make -C $(LIBMLX)/build -j4 + +%.o: %.c + @$(CC) $(CFLAGS) -o $@ -c $< $(HEADERS) && printf "Compiling: $(notdir $<)" + +$(NAME): $(OBJS) + @$(CC) $(OBJS) $(LIBS) $(HEADERS) -o $(NAME) + +clean: + @rm -rf $(OBJS) + @rm -rf $(LIBMLX)/build + +fclean: clean + @rm -rf $(NAME) + +re: clean all + +.PHONY: all, clean, fclean, re, libmlx \ No newline at end of file diff --git a/includes/cub3d.h b/includes/cub3d.h new file mode 100644 index 0000000..fae34bf --- /dev/null +++ b/includes/cub3d.h @@ -0,0 +1,35 @@ + +#ifndef CUB3D_H + +# define CUB3D_H + +# include +# include +# include +# include "../lib/mlx/include/MLX42/MLX42.h" + +# define S_W 800 +# define S_H 600 +# define FOV 60 +# define TILE_SIZE 50 + +typedef struct s_player +{ + int player_x; + int player_y; + double angel; + float fov; + int rot; + int l_r; + int u_d; +} t_player; + +typedef struct s_mlx +{ + mlx_image_t *img; + mlx_t *mlx_ptr; + t_player *player; + char **map; +} t_mlx; + +#endif \ No newline at end of file diff --git a/lib/mlx b/lib/mlx new file mode 160000 index 0000000..5b5b7a1 --- /dev/null +++ b/lib/mlx @@ -0,0 +1 @@ +Subproject commit 5b5b7a1a66c992866dac0216176160be056954a4 diff --git a/raw.txt b/raw.txt new file mode 100644 index 0000000..f866538 --- /dev/null +++ b/raw.txt @@ -0,0 +1,1396 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* 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); +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..0efa6bd --- /dev/null +++ b/src/main.c @@ -0,0 +1,117 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* main.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: aortigos player_x + i, player->player_y + j, color); +} + +void draw_map(mlx_image_t *img, char **map) +{ + int x, y, i, j; + + i = 0; + while (map[i]) + { + j = 0; + while (map[i][j]) + { + if (map[i][j] == '1') + { + for (y = 0; y < TILE_SIZE; y++) + for (x = 0; x < TILE_SIZE; x++) + mlx_put_pixel(img, j * TILE_SIZE + x, i * TILE_SIZE + y, 0xFFFFFFFF); + } + j++; + } + i++; + } +} + +// ------------------ Input ------------------ + +void key_hook(mlx_key_data_t keydata, void *param) +{ + t_player *player = (t_player *)param; + + if (keydata.key == MLX_KEY_W && keydata.action == MLX_PRESS) + player->player_y -= 10; + if (keydata.key == MLX_KEY_S && keydata.action == MLX_PRESS) + player->player_y += 10; + if (keydata.key == MLX_KEY_A && keydata.action == MLX_PRESS) + player->player_x -= 10; + if (keydata.key == MLX_KEY_D && keydata.action == MLX_PRESS) + player->player_x += 10; +} + +// ------------------ Game Loop ------------------ + +void game_loop(void *param) +{ + t_mlx *mlx_data = (t_mlx *)param; + + for (int y = 0; y < S_H; y++) + for (int x = 0; x < S_W; x++) + mlx_put_pixel(mlx_data->img, x, y, 0x000000FF); // negro + draw_map(mlx_data->img, mlx_data->map); // dibujar mapa + draw_player(mlx_data->img, mlx_data->player, 0xFF0000FF); // dibujar jugador +} + +// ------------------ Main ------------------ + +int main(void) +{ + mlx_t *mlx; + mlx_image_t *img; + t_player player; + t_mlx mlx_data; + + // mapa simple + char *map[] = { + "111111111", + "100000011", + "101000001", + "100001001", + "111111111", + NULL + }; + + // inicializar MLX + mlx = mlx_init(S_W, S_H, "Cub3D", false); + if (!mlx) + return (1); + + img = mlx_new_image(mlx, S_W, S_H); + mlx_image_to_window(mlx, img, 0, 0); + + // inicializar jugador + player.player_x = 100; + player.player_y = 100; + + // inicializar estructura de MLX + mlx_data.mlx_ptr = mlx; + mlx_data.img = img; + mlx_data.player = &player; + mlx_data.map = map; + + // hooks + mlx_key_hook(mlx, key_hook, &player); + mlx_loop_hook(mlx, game_loop, &mlx_data); + + // loop + mlx_loop(mlx); + + return (0); +} \ No newline at end of file