diff --git a/Makefile b/Makefile index 82d5c97..4ef9264 100644 --- a/Makefile +++ b/Makefile @@ -1,45 +1,71 @@ -# **************************************************************************** # -# # -# ::: :::::::: # -# Makefile :+: :+: :+: # -# +:+ +:+ +:+ # -# By: mcolonna +#+ +:+ +#+ # -# +#+#+#+#+#+ +#+ # -# Created: 2024/07/29 13:08:42 by greg #+# #+# # -# Updated: 2024/10/15 13:01:09 by mcolonna ### ########.fr # -# # -# **************************************************************************** # - NAME = cub3d +CPP = gcc $(FLAGS) +LIBRARIES_DIR = Libft Minilibx +LIBRARIES_A = Libft/libft.a Minilibx/libmlx.a +CPP_1 = $(CPP) -Wall -Wextra -Werror -I Libft -I Minilibx $(FLAGS_1) +CPP_2 = $(CPP) $(FLAGS_2) +SHARED = -lX11 -lXext -lm +C_FILES = $(wildcard **.c) +O_FILES = $(patsubst %.c,%.o,$(C_FILES)) -SRC = $(wildcard *.c) +ECHO = echoo(){ \ + if [ -t 1 ]; then \ + echo "$$*"; \ + else \ + echo "$$*" | sed -E "s/\x1B[[][0-9;]+m//g"; \ + fi; \ +};echoo -OBJS = ${SRC:.c=.o} +all : $(NAME) -LIBFT = Libft - -MLX = Minilibx - -CC = gcc -g - -CFLAGS = -Wall -Werror -Wextra - -all: $(NAME) - -obj : ${OBJS} - -$(NAME): ${OBJS} - - make -C ${LIBFT} - make -C ${MLX} - gcc ${OBJS} Libft/libft.a Minilibx/libmlx.a -lX11 -lXext -o cub3d -lm +$(LIBRARIES_DIR): + @$(ECHO) + @$(ECHO) "\e[30;47;1m $(NAME): making library $@... \e[0m" + $(MAKE) -C $@ clean : - rm -f ${OBJS} + @$(ECHO) + @$(ECHO) "\e[30;47;1m $(NAME): clean... \e[0m" + -rm -f $(O_FILES) -fclean : clean - rm -f $(NAME) - make fclean -C ${LIBFT} - make clean -C ${MLX} +fclean : clean + @$(ECHO) + @$(ECHO) "\e[30;47;1m $(NAME): fclean... \e[0m" + -rm -f $(NAME) re : fclean all + +$(NAME) : $(O_FILES) $(LIBRARIES_DIR) + @$(ECHO) + @$(ECHO) "\e[30;47;1m $(NAME): linking... \e[0m" + $(CPP_2) $(O_FILES) $(LIBRARIES_A) $(SHARED) -o $@ + @$(ECHO) + @$(ECHO) "\t\t \e[0;92m\(^o^)/ \e[0;102;30;1m $(NAME) made! \e[0;92m \(^o^)/\e[0m" + @$(ECHO) + +%.o : %.c + @$(ECHO) + @$(ECHO) "\e[30;47;1m $(NAME): making '$@'... \e[0m" + $(CPP_1) $(FLAGS_1) -c $< -o $@ + +check_headers : + @ERROR=0; \ + for HEADER in $(wildcard *.h) $(wildcard **/*.h); \ + do \ + echo "check header $$HEADER..."; \ + > __tmp_check_header.c echo "#include \"$$HEADER\""; \ + >> __tmp_check_header.c echo "#include \"$$HEADER\""; \ + >> __tmp_check_header.c echo "int main(void) {}"; \ + $(CPP) -o __tmp_check_header.out __tmp_check_header.c; \ + if [ $$? -ne 0 ]; \ + then \ + ERROR=1; \ + echo " error \e[31m:(\e[0m"; \ + fi; \ + echo " good \e[32m:)\e[0m"; \ + 2> /dev/null rm -- "__tmp_check_header.out" "__tmp_check_header.c"; \ + done; \ + 2> /dev/null rm __tmp_check_header.out __tmp_check_header.c; \ + if [ $$ERROR -eq 0 ]; then true; else false; fi; + +.PHONY : all clean fclean re check_headers $(LIBRARIES_DIR) diff --git a/algo.c b/algo.c index 382d100..08bdf5c 100644 --- a/algo.c +++ b/algo.c @@ -6,52 +6,16 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/10/01 16:24:58 by grobledo #+# #+# */ -/* Updated: 2024/10/15 16:00:41 by mcolonna ### ########.fr */ +/* Updated: 2024/10/15 16:38:31 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ #include "algo.h" -void *g_mlx = NULL; -void *g_win = NULL; -t_ray g_ray; - -int g_world_map[MAP_WIDTH][MAP_HEIGHT] = { -{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, -{1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, -{1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, -{1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, -{1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1}, -{1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, -{1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1}, -{1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, -{1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1}, -{1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, -{1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, -{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, -{1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, -{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, -{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, -{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, -{1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, -{1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, -{1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, -{1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, -{1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, -{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, -{1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, -{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} -}; - -// TODO from map - -static int initalgo(void) -{ - g_ray.pos.x = 14; - g_ray.pos.y = 6.5; - g_ray.rot = 0; - return (0); -} +void *g_mlx = NULL; +void *g_win = NULL; +t_map g_map; +t_player g_player; // TODO manage image format error better @@ -90,11 +54,17 @@ void load_textures(t_tex *tex) &width, &height); } -int main(void) +int main(int argc, char *argv[]) { g_mlx = mlx_init(); + if (argc != 2) + { + printf("Syntax: %s \n", argv[0]); + return (1); + } + if (!map_from_file(&g_map, argv[1])) + return (1); g_win = mlx_new_window(g_mlx, SCREEN_WIDTH, SCREEN_HEIGHT, "cub3d"); - initalgo(); mlx_hook(g_win, KeyPress, KeyPressMask, keypress, NULL); draw_screen(); mlx_loop(g_mlx); diff --git a/algo.h b/algo.h index 0a30eee..55be665 100644 --- a/algo.h +++ b/algo.h @@ -6,7 +6,7 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/09/30 15:45:59 by grobledo #+# #+# */ -/* Updated: 2024/10/15 15:48:45 by mcolonna ### ########.fr */ +/* Updated: 2024/10/15 16:57:48 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ @@ -15,11 +15,17 @@ # include # include +# include # include # include "Minilibx/mlx.h" # include "Minilibx/mlx_int.h" # include "Libft/libft.h" +# include "stream.h" +# include "read_all_text.h" +# include "map.h" +# include "map_mapping.h" + # define MAP_WIDTH 24 // cases (TODO test) # define MAP_HEIGHT 24 // cases (TODO test) # define TEX_WIDTH 64 @@ -34,30 +40,10 @@ # define SCREEN_HEIGHT 480 // px # define FOV 0.66 // ? TODO unit -typedef struct s_point_double -{ - double x; - double y; -} t_point_double; - -typedef struct s_point_int -{ - int x; - int y; -} t_point_int; - -typedef struct s_ray -{ - // pos player on map (cases) - t_point_double pos; - // player rotation (rad) - double rot; -} t_ray; - extern void *g_mlx; extern void *g_win; -extern t_ray g_ray; -extern int g_world_map[MAP_WIDTH][MAP_HEIGHT]; +extern t_player g_player; +extern t_map g_map; typedef struct s_tex { @@ -69,6 +55,11 @@ typedef struct s_tex } t_tex; +/// @brief Write an error message on stderr. +/// +/// @param str... All the strings to write. The last parameter MUST BE NULL. +void write_err(const char *str, ...); + void vector_from_rotation(t_point_double *vec, double angle, double norm); int keypress(int keycode); diff --git a/color.c b/color.c new file mode 100644 index 0000000..13b2deb --- /dev/null +++ b/color.c @@ -0,0 +1,18 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* color.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/10/01 17:04:56 by mcolonna #+# #+# */ +/* Updated: 2024/10/15 16:26:52 by mcolonna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "map.h" + +t_color color_from_rgb(int red, int green, int blue) +{ + return (red << 16 | green << 8 | blue); +} diff --git a/dev/cub.vim b/dev/cub.vim new file mode 100644 index 0000000..49b1f11 --- /dev/null +++ b/dev/cub.vim @@ -0,0 +1,23 @@ +# Vim plugin to edit .cub files + +function! CubSyntax() +if expand('%:e') == 'cub' + +highlight cubParameter ctermfg=blue +syntax match cubParameter /^(NO|SO|WE|EA|F|C) .$/ + +highlight cubDefault ctermfg=white +syntax match cubDefault /./ + +highlight cub0 ctermfg=grey +syntax match cub0 /0/ + +highlight cub1 cterm=bold ctermfg=white +syntax match cub1 /1/ + +highlight cubP cterm=bold ctermfg=blue +syntax match cubP /[NSWE]/ + +endif +endfunction +autocmd BufReadPost * call CubSyntax() diff --git a/map.h b/map.h new file mode 100644 index 0000000..cc974fd --- /dev/null +++ b/map.h @@ -0,0 +1,134 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* map.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/10/01 13:59:04 by mcolonna #+# #+# */ +/* Updated: 2024/10/15 18:22:32 by mcolonna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef MAP_H +# define MAP_H + +# include +# include "utils.h" + +/// @brief The type of a case. +typedef enum e_map_wall +{ + /// @brief Empty case, for '0' and ' '. + EMPTY, + /// @brief A wall, for '1'. + WALL, +} t_map_wall; + +/// @brief An object of the map (player, enemies?) +typedef struct s_object +{ + /// @brief Function called when creating the object. + /// + /// @param data Address of the s_object.data pointer. + void (*init)(void **data, t_point_int pos); + + /// @brief Function called when destroying the object (to avoid leaks). + /// + /// @param data Address of the s_object.data pointer. + void (*destroy)(void **data, t_point_int pos); + + /// @brief Function called each tick. + /// + /// @param data Address of the s_object.data pointer. + void (*tick)(void **data, t_point_int pos); + + /// @brief Pointer the object can use to save data. + void *data; +} t_object; + +/// @brief Represents a case of the map. +typedef struct s_map_case +{ + /// @brief 'true' if the case is inside of the room (false with ' ' char) + bool inside; + + /// @brief Is the case empty or a wall? + t_map_wall wall; + + /// @brief The object that appears on this case. If there is none, + /// every pointer of the struct will be NULL. + t_object object; +} t_map_case; + +typedef struct s_player +{ + // pos player on map (cases) + t_point_double pos; + // player rotation (rad) + double rot; +} t_player; + +/// @brief Represents a map. +typedef struct s_map +{ + /// @brief Color of the floor. + t_color color_floor; + + /// @brief Color of the ceiling. + t_color color_ceiling; + + /// @brief Path to the image file for the wall face north. + const char *texture_north; + + /// @brief Path to the image file for the wall face south. + const char *texture_south; + + /// @brief Path to the image file for the wall face west. + const char *texture_west; + + /// @brief Path to the image file for the wall face east. + const char *texture_east; + + /// @brief Width of the map. + unsigned int width; + + /// @brief Height of the map. + unsigned int height; + + /// @brief An 2D array of all the cases. + /// + /// Syntax to get a case: cases[y * width + x] + /// x is left to right, y is top to bottom. + t_map_case *cases; + + /// @brief Represents the player in the map. + t_player player; +} t_map; + +/// @brief Create a t_map from the content of a .cub file. +/// +/// @param dest Pointer to the t_map to set. +/// @param file .cub file to use to create the t_map. +/// It must be destroyed with mapDestroy to avoid leaks. +/// @return false if an error occured, otherwise true. +bool map_from_file(t_map *dest, const char *file); + +/// @brief Destroy the map to avoid leaks. +void map_destroy(t_map *map); + +/// @brief Return true if the map is valid. Write an error message on stderr. +/// +/// @param map The map to check. +/// @return true if the map is valid, false if not. +bool check_map(const t_map *map); + +/// @brief Get a case of the map from its coordinates. +/// +/// @param map Map to get the case from. +/// @param x x position of the case to return. +/// @param y y position of the case to return. +/// @return Wanted case. +const t_map_case *map_get_case(const t_map *map, int x, int y); + +#endif diff --git a/map1.c b/map1.c new file mode 100644 index 0000000..aaba9c0 --- /dev/null +++ b/map1.c @@ -0,0 +1,123 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* map1.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/10/01 17:12:58 by mcolonna #+# #+# */ +/* Updated: 2024/10/15 17:22:53 by mcolonna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "map.h" +#include "map_utils.h" +#include "stream.h" +#include "read_all_text.h" +#include "libft.h" +#include +#include +#include +#include +#include + +static bool map_from_file2(t_map *dest, t_stream *stream, int fd) +{ + bool success; + + stream->i = 0; + success = read_map(dest, stream); + if (success) + { + success = check_map(dest); + if (!success) + map_destroy(dest); + } + close(fd); + free((void *)stream->str); + map_init_objects(dest); + return (success); +} + +bool map_from_file(t_map *dest, const char *file) +{ + int fd; + t_stream stream; + + if (ft_strncmp(file + ft_strlen(file) - 4, ".cub", 5)) + { + write_err("File extension must be .cub\n", NULL); + return (false); + } + fd = open(file, O_RDONLY); + if (fd < 0) + { + write_err("Can't open '", file, "': ", strerror(errno), "\n", + NULL); + return (false); + } + stream.str = read_all_text(fd); + if (!stream.str) + { + write_err("Can't read file.\n", NULL); + close(fd); + return (false); + } + return (map_from_file2(dest, &stream, fd)); +} + +void map_destroy(t_map *map) +{ + free((void *)map->texture_east); + free((void *)map->texture_west); + free((void *)map->texture_north); + free((void *)map->texture_south); + free(map->cases); +} + +static bool check_map2(const t_map *map, unsigned int x, unsigned int y) +{ + unsigned int x2; + unsigned int y2; + const t_map_case *c; + + c = &map->cases[y * map->width + x]; + if (c->inside && c->wall != WALL) + { + if (x == 0 || x == map->width - 1 + || y == 0 || y == map->height - 1) + return (write_err("Map is not surrounded by walls\n", NULL), false); + x2 = x - 2; + while (++x2 < x + 2) + { + y2 = y - 2; + while (++y2 < y + 2) + { + if (x < map->width && y < map->height + && !map->cases[y2 * map->width + x2].inside) + return (write_err("Map is not surrounded by walls\n", NULL), + false); + } + } + } + return (true); +} + +// TODO check player +bool check_map(const t_map *map) +{ + unsigned int x; + unsigned int y; + + x = -1; + while (++x < map->width) + { + y = -1; + while (++y < map->height) + { + if (!check_map2(map, x, y)) + return (false); + } + } + return (true); +} diff --git a/map2.c b/map2.c new file mode 100644 index 0000000..f4b99f5 --- /dev/null +++ b/map2.c @@ -0,0 +1,27 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* map2.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/10/01 17:12:58 by mcolonna #+# #+# */ +/* Updated: 2024/10/15 16:44:40 by mcolonna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "map.h" +#include "map_utils.h" +#include "stream.h" +#include "read_all_text.h" +#include "libft.h" +#include +#include +#include +#include +#include + +const t_map_case *map_get_case(const t_map *map, int x, int y) +{ + return (&map->cases[y * map->width + x]); +} diff --git a/map_mapping.c b/map_mapping.c new file mode 100644 index 0000000..129ce34 --- /dev/null +++ b/map_mapping.c @@ -0,0 +1,25 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* map_mapping.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/10/04 12:05:21 by mcolonna #+# #+# */ +/* Updated: 2024/10/15 17:19:26 by mcolonna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "map_mapping.h" +#include "player.h" +#include + +const t_map_mapping_element g_map_mapping[] = { +{' ', {false, EMPTY, {NULL, NULL, NULL, NULL}}}, +{'0', {true, EMPTY, {NULL, NULL, NULL, NULL}}}, +{'1', {true, WALL, {NULL, NULL, NULL, NULL}}}, +{'N', {true, EMPTY, {init_player_n, NULL, NULL, NULL}}}, +{'S', {true, EMPTY, {init_player_s, NULL, NULL, NULL}}}, +{'E', {true, EMPTY, {init_player_e, NULL, NULL, NULL}}}, +{'W', {true, EMPTY, {init_player_w, NULL, NULL, NULL}}}, +{'\0', {true, EMPTY, {NULL, NULL, NULL, NULL}}}}; diff --git a/map_mapping.h b/map_mapping.h new file mode 100644 index 0000000..5a3b2c9 --- /dev/null +++ b/map_mapping.h @@ -0,0 +1,31 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* map_mapping.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/10/04 12:00:07 by mcolonna #+# #+# */ +/* Updated: 2024/10/04 15:24:14 by mcolonna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef MAP_MAPPING_H +# define MAP_MAPPING_H + +# include "map.h" + +/// @brief Each element of g_map_mapping. A case and its associated char. +typedef struct s_map_mapping_element +{ + /// @brief char representing the case. + char name; + /// @brief associated case. + t_map_case value; +} t_map_mapping_element; + +/// @brief List of each char and its according case. +/// Ended by an element with the name '\0'. +extern const t_map_mapping_element g_map_mapping[]; + +#endif diff --git a/map_utils.h b/map_utils.h new file mode 100644 index 0000000..733d6f4 --- /dev/null +++ b/map_utils.h @@ -0,0 +1,83 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* map_utils.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/10/03 15:05:13 by mc #+# #+# */ +/* Updated: 2024/10/15 17:23:40 by mcolonna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef MAP_UTILS_H +# define MAP_UTILS_H + +# include "stream.h" +# include "map.h" +# include +# include + +/// @brief Read a parameter of the map which has a color as an argument. +/// Color format: [0-255],[0-255],[0-255] +/// @param name Name of the parameter. +/// @param dest Will be set to the value of the parameter. +/// Unchanged if error. +/// If success but *dest is not 0xFF000000, throws an error. +/// @param stream Stream to use. +/// Unchanged if error. +/// @param redefined Set to true if the parameter was already defined. +/// @return true if success or redefined, false if non-fatal error. +bool read_color_parameter(const char *name, t_color *dest, + t_stream *stream, bool *redefined); + +/// @brief Read a parameter of the map which has a string as an argument. +/// @param name Name of the parameter. +/// @param dest Will be set to an alloc'd pointer to the value of the parameter. +/// Unchanged if error. +/// If success but *dest is not null, throws an error. +/// @param stream Stream to use. +/// Unchanged if error. +/// @param redefined Set to true if the parameter was already defined. +/// @return true if success or redefined, false if non-fatal error. +bool read_string_parameter(const char *name, const char **dest, + t_stream *stream, bool *redefined); + +/// @brief Set the map to initial values. Every texture becomes NULL +/// and every color becomes 0xFF000000. +/// @param dest Map to reset. +void reset_map(t_map *dest); + +/// @brief Read a map-formatted string. +/// If an error occurs, write an error message on stderr. +/// @param dest Will be set to the map. +/// @param stream Stream to use. +/// @return true if success, false if error. +bool read_map(t_map *dest, t_stream *stream); + +/// @brief Get the case associated with the char. +/// +/// @param dest Will be set to the char. +/// @param name Name of the case. +/// @return true if success, false if error. +bool get_case(t_map_case *dest, char name); + +/// @brief Fill the pointer with 'size' null bytes. +/// +/// @param dest The pointer to set. +/// @param size The number of bytes. +void fill_zeros(void *dest, size_t size); + +/// @brief Read the map description part of the map. +/// Read until the end of the file. +/// +/// @param map The .width, .height and .cases members will be set. +/// @param stream Stream to use. +/// @return true if success, false if error. +bool read_map_description(t_map *map, t_stream *stream); + +/// @brief Initialize all objects of the map. +/// @param map Map to use. +void map_init_objects(t_map *map); + +#endif diff --git a/map_utils1.c b/map_utils1.c new file mode 100644 index 0000000..5b8acd2 --- /dev/null +++ b/map_utils1.c @@ -0,0 +1,135 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* map_utils1.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/10/03 15:02:09 by mc #+# #+# */ +/* Updated: 2024/10/15 17:43:29 by mcolonna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "map_utils.h" +#include "map.h" +#include "map_mapping.h" +#include + +bool read_color_parameter(const char *name, t_color *dest, + t_stream *stream, bool *redefined) +{ + unsigned int rgb[3]; + bool err; + t_stream old; + + old = *stream; + err = false; + read_expected_string(name, stream, &err); + read_expected_string(" ", stream, &err); + read_unsigned(&rgb[0], stream, &err); + read_expected_string(",", stream, &err); + read_unsigned(&rgb[1], stream, &err); + read_expected_string(",", stream, &err); + read_unsigned(&rgb[2], stream, &err); + read_expected_string("\n", stream, &err); + if (!err && *dest != 0xFF000000) + { + *redefined = true; + write_err("Parameter '", name, "' was defined several times\n", + NULL); + } + else if (!err) + *dest = color_from_rgb(rgb[0], rgb[1], rgb[2]); + else + *stream = old; + return (!err); +} + +bool read_string_parameter(const char *name, const char **dest, + t_stream *stream, bool *redefined) +{ + char *r; + bool err; + t_stream old; + + old = *stream; + err = false; + r = NULL; + read_expected_string(name, stream, &err); + read_expected_string(" ", stream, &err); + read_until('\n', &r, stream, &err); + read_expected_string("\n", stream, &err); + if (!err && *dest) + { + *redefined = true; + write_err("Parameter '", name, "' was defined several times\n", NULL); + } + if (*redefined || err) + { + *stream = old; + free(r); + } + else + *dest = r; + return (!err); +} + +void reset_map(t_map *dest) +{ + dest->cases = NULL; + dest->color_ceiling = 0xFF000000; + dest->color_floor = 0xFF000000; + dest->texture_east = NULL; + dest->texture_west = NULL; + dest->texture_north = NULL; + dest->texture_south = NULL; +} + +bool read_map(t_map *dest, t_stream *stream) +{ + bool err; + bool rdf; + + reset_map(dest); + err = false; + rdf = false; + while (!rdf && !err && stream->str[stream->i]) + { + if ((read_expected_string("\n", stream, &err), err) + && !read_string_parameter("NO", &dest->texture_north, stream, &rdf) + && !read_string_parameter("SO", &dest->texture_south, stream, &rdf) + && !read_string_parameter("WE", &dest->texture_west, stream, &rdf) + && !read_string_parameter("EA", &dest->texture_east, stream, &rdf) + && !read_color_parameter("F", &dest->color_floor, stream, &rdf) + && !read_color_parameter("C", &dest->color_ceiling, stream, &rdf)) + { + err = !read_map_description(dest, stream); + break ; + } + err = false; + } + if (!rdf && !dest->cases) + err = (write_err("Map description missing\n", NULL), true); + (rdf || err) && (map_destroy(dest), false); + return (!err && !rdf && dest->cases); +} + +void map_init_objects(t_map *map) +{ + t_point_int pos; + int i; + + pos.x = 0; + while (pos.x < (int)map->width) + { + pos.y = 0; + while (pos.y < (int)map->height) + { + i = pos.y * map->width + pos.x; + if (map->cases[i].object.init) + map->cases[i].object.init(&map->cases[i].object.data, pos); + pos.y++; + } + pos.x++; + } +} diff --git a/map_utils2.c b/map_utils2.c new file mode 100644 index 0000000..b15565a --- /dev/null +++ b/map_utils2.c @@ -0,0 +1,105 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* map_utils2.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/10/04 15:12:08 by mcolonna #+# #+# */ +/* Updated: 2024/10/15 16:27:41 by mcolonna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "map_utils.h" +#include "map_mapping.h" +#include "map.h" +#include + +/// @brief Read the map description to get the dimensions. +/// The map must be at least 1x1. +/// +/// @param map The .width and .height members will be set. +/// @param stream Stream to use. +/// @return true if success, false if error. +static bool get_map_dimensions(t_map *map, t_stream *stream) +{ + unsigned int x; + unsigned int y; + + map->width = 0; + map->height = 0; + y = 0; + while (stream->str[stream->i]) + { + x = 0; + while (stream->str[stream->i] && stream->str[stream->i] != '\n') + { + stream->i++; + x++; + } + if (x > map->width) + map->width = x; + if (stream->str[stream->i] == '\n') + stream->i++; + y++; + } + map->height = y; + return (map->width > 0 && map->height > 0); +} + +bool get_case(t_map_case *dest, char name) +{ + int i; + char tmp[2]; + + i = -1; + while (g_map_mapping[++i].name) + { + if (name == g_map_mapping[i].name) + { + *dest = g_map_mapping[i].value; + return (true); + } + } + tmp[0] = name; + tmp[1] = '\0'; + write_err("Character '", tmp, "' unexpected\n", NULL); + return (false); +} + +void fill_zeros(void *dest, size_t size) +{ + size_t i; + + i = -1; + while (++i < size) + ((char *)dest)[i] = '\0'; +} + +bool read_map_description(t_map *map, t_stream *stream) +{ + t_stream stream2; + unsigned int x; + unsigned int y; + + stream2 = *stream; + if (!get_map_dimensions(map, &stream2)) + return (false); + map->cases = malloc((map->width * map->height) * sizeof(t_map_case)); + y = -1; + fill_zeros(map->cases, (map->width * map->height) * sizeof(t_map_case)); + while (++y < map->height) + { + x = 0; + while (stream->str[stream->i] && stream->str[stream->i] != '\n') + { + if (!get_case(&map->cases[y * map->width + x], + stream->str[stream->i])) + return (false); + stream->i++; + x++; + } + stream->i++; + } + return (true); +} diff --git a/move.c b/move.c index 0646614..7d2436e 100644 --- a/move.c +++ b/move.c @@ -6,53 +6,35 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/10/15 12:47:34 by mcolonna #+# #+# */ -/* Updated: 2024/10/15 16:01:08 by mcolonna ### ########.fr */ +/* Updated: 2024/10/15 18:22:58 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ #include "algo.h" -static int move_forward(void) +static int move(int factor) { t_point_double dir; - vector_from_rotation(&dir, g_ray.rot, 1); - if (g_world_map[(int)((g_ray.pos.x + dir.x * MOVE_SPEED))] - [(int)(g_ray.pos.y)] != 1 + vector_from_rotation(&dir, g_map.player.rot, 1); + if (map_get_case(&g_map, + (int)(g_map.player.pos.x + dir.x * MOVE_SPEED * factor), + (int)(g_map.player.pos.y) + )->wall == EMPTY ) - g_ray.pos.x += dir.x * MOVE_SPEED; - if (g_world_map[(int)(g_ray.pos.x)] - [(int)(g_ray.pos.y + dir.y * MOVE_SPEED)] != 1 + g_map.player.pos.x += dir.x * MOVE_SPEED; + if (map_get_case(&g_map, + (int)(g_map.player.pos.x), + (int)(g_map.player.pos.y + dir.y * MOVE_SPEED * factor) + )->wall == EMPTY ) - g_ray.pos.y += dir.y * MOVE_SPEED; + g_map.player.pos.y += dir.y * MOVE_SPEED * factor; return (0); } -static int move_backward(void) +static int rotate(int factor) { - t_point_double dir; - - vector_from_rotation(&dir, g_ray.rot, 1); - if (g_world_map[(int)(g_ray.pos.x - dir.x * MOVE_SPEED)] - [(int)(g_ray.pos.y)] != 1 - ) - g_ray.pos.x -= dir.x * MOVE_SPEED; - if (g_world_map[(int)(g_ray.pos.x)] - [(int)(g_ray.pos.y - dir.y * MOVE_SPEED)] != 1 - ) - g_ray.pos.y -= dir.y * MOVE_SPEED; - return (0); -} - -static int move_right(void) -{ - g_ray.rot += PI / ROT_SPEED_DIVIDE_PI; - return (0); -} - -static int move_left(void) -{ - g_ray.rot -= PI / ROT_SPEED_DIVIDE_PI; + g_map.player.rot += PI / ROT_SPEED_DIVIDE_PI * factor; return (0); } @@ -61,13 +43,13 @@ static int move_left(void) int keypress(int keycode) { if (keycode == XK_Up || keycode == XK_z || keycode == XK_w) - move_forward(); + move(+1); if (keycode == XK_Down || keycode == XK_s) - move_backward(); + move(-1); if (keycode == XK_Right || keycode == XK_d) - move_right(); + rotate(+1); if (keycode == XK_Left || keycode == XK_q || keycode == XK_a) - move_left(); + rotate(-1); if (keycode == XK_Escape) { mlx_destroy_window(g_mlx, g_win); diff --git a/player.c b/player.c new file mode 100644 index 0000000..98b46af --- /dev/null +++ b/player.c @@ -0,0 +1,46 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* player.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/10/15 17:33:11 by mcolonna #+# #+# */ +/* Updated: 2024/10/15 17:38:27 by mcolonna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "player.h" +#include "utils.h" +#include "algo.h" + +static void init_player(t_point_int pos, double rot) +{ + g_map.player.pos.x = pos.x + 0.5; + g_map.player.pos.y = pos.y + 0.5; + g_map.player.rot = rot; +} + +void init_player_n(void **data, t_point_int pos) +{ + (void)data; + init_player(pos, 0); +} + +void init_player_s(void **data, t_point_int pos) +{ + (void)data; + init_player(pos, PI); +} + +void init_player_w(void **data, t_point_int pos) +{ + (void)data; + init_player(pos, 3 * PI / 2); +} + +void init_player_e(void **data, t_point_int pos) +{ + (void)data; + init_player(pos, PI / 2); +} diff --git a/player.h b/player.h new file mode 100644 index 0000000..e9dfb28 --- /dev/null +++ b/player.h @@ -0,0 +1,23 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* player.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/10/15 17:31:35 by mcolonna #+# #+# */ +/* Updated: 2024/10/15 17:43:52 by mcolonna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef PLAYER_H +# define PLAYER_H + +# include "utils.h" + +void init_player_n(void **data, t_point_int pos); +void init_player_s(void **data, t_point_int pos); +void init_player_w(void **data, t_point_int pos); +void init_player_e(void **data, t_point_int pos); + +#endif diff --git a/read_all_text.c b/read_all_text.c new file mode 100644 index 0000000..42abe10 --- /dev/null +++ b/read_all_text.c @@ -0,0 +1,95 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* read_all_text.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/10/02 16:18:35 by mcolonna #+# #+# */ +/* Updated: 2024/10/15 16:28:22 by mcolonna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "read_all_text.h" +#include "map.h" +#include "libft.h" +#include +#include +#include + +/// @brief Concatenate *dest and src and put the result in *dest. +/// +/// *dest is alloc'd to contain the result value. +/// +/// the old *dest is freed only if the function succeds. +/// +/// src doesn't have to be nul-terminated, instead n is the size of src. +/// +/// @return true if success, false if error. +static bool strconcat(char **dest, char *src, int n) +{ + const int len_dest = ft_strlen(*dest); + char *old_dest; + int i; + + old_dest = *dest; + *dest = malloc((len_dest + n + 1) * sizeof(char)); + if (!*dest) + return (false); + i = -1; + while (old_dest[++i]) + (*dest)[i] = old_dest[i]; + while (i < len_dest + n) + { + (*dest)[i] = src[i - len_dest]; + i++; + } + (*dest)[i] = '\0'; + free(old_dest); + return (true); +} + +/// @brief If the string isn't empty and isn't ended by a '\\n', add one and +/// return the result. +/// +/// str is either returned directly, or another freeable pointer is returned +/// and str is freed. +/// +/// @return Return the result or NULL if error. +static char *add_endline_if_necessary(char *str) +{ + char *endline; + + if (str[0] == '\0' || str[ft_strlen(str) - 1] == '\n') + return (str); + endline = malloc(1 * sizeof(char)); + if (!endline) + return (free(str), NULL); + endline[0] = '\n'; + if (!strconcat(&str, endline, 1)) + return (free(str), NULL); + return (str); +} + +char *read_all_text(int fd) +{ + char buf[BUFFER_SIZE]; + int n; + char *r; + + r = malloc(sizeof(char)); + if (!r) + return (NULL); + r[0] = '\0'; + n = 1; + while (n) + { + n = read(fd, buf, BUFFER_SIZE); + if (n < 0 || (n && !strconcat(&r, buf, n))) + { + free(r); + return (NULL); + } + } + return (add_endline_if_necessary(r)); +} diff --git a/read_all_text.h b/read_all_text.h new file mode 100644 index 0000000..f86eec9 --- /dev/null +++ b/read_all_text.h @@ -0,0 +1,29 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* read_all_text.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/10/02 15:39:02 by mcolonna #+# #+# */ +/* Updated: 2024/10/02 17:04:33 by mcolonna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef READ_ALL_TEXT_H +# define READ_ALL_TEXT_H + +/// @brief Size of buffer used in read_all_text(). +# define BUFFER_SIZE 1000 + +/// @brief Read all the text of the given file. +/// +/// If the last line isn't ended by a '\\n', add one. +/// +/// If error, returns NULL and set errno accordingly. +/// +/// @param fd File descriptor of the file. +/// @return Alloc'd string of the file content. NULL if error. +char *read_all_text(int fd); + +#endif diff --git a/render.c b/render.c index 6dc4581..6279fd5 100644 --- a/render.c +++ b/render.c @@ -6,7 +6,7 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/10/14 14:55:05 by greg #+# #+# */ -/* Updated: 2024/10/15 15:59:55 by mcolonna ### ########.fr */ +/* Updated: 2024/10/15 16:55:02 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,8 +19,8 @@ static void calculate_perpwalldist3(int x, t_point_double plane; t_point_double dir; - vector_from_rotation(&dir, g_ray.rot, 1); - vector_from_rotation(&plane, g_ray.rot + PI / 2, 1); + vector_from_rotation(&dir, g_map.player.rot, 1); + vector_from_rotation(&plane, g_map.player.rot + PI / 2, 1); raydir->x = dir.x + plane.x * ray_direction; raydir->y = dir.y + plane.y * ray_direction; deltadist->x = 1e30; @@ -36,30 +36,30 @@ static void calculate_perpwalldist2(int x, t_point_double *deltadist, t_point_int *step) { - const int map_x = (int)g_ray.pos.x; - const int map_y = (int)g_ray.pos.y; + const int map_x = (int)g_map.player.pos.x; + const int map_y = (int)g_map.player.pos.y; t_point_double raydir; calculate_perpwalldist3(x, &raydir, deltadist); if (raydir.x < 0) { step->x = -1; - sidedist->x = (g_ray.pos.x - map_x) * deltadist->x; + sidedist->x = (g_map.player.pos.x - map_x) * deltadist->x; } else { step->x = 1; - sidedist->x = (map_x + 1.0 - g_ray.pos.x) * deltadist->x; + sidedist->x = (map_x + 1.0 - g_map.player.pos.x) * deltadist->x; } if (raydir.y < 0) { step->y = -1; - sidedist->y = (g_ray.pos.y - map_y) * deltadist->y; + sidedist->y = (g_map.player.pos.y - map_y) * deltadist->y; } else { step->y = 1; - sidedist->y = (map_y + 1.0 - g_ray.pos.y) * deltadist->y; + sidedist->y = (map_y + 1.0 - g_map.player.pos.y) * deltadist->y; } } @@ -76,10 +76,10 @@ static double calculate_perpwalldist(int x) t_point_double deltadist; t_point_int step; - map_pos.x = (int)g_ray.pos.x; - map_pos.y = (int)g_ray.pos.y; + map_pos.x = (int)g_map.player.pos.x; + map_pos.y = (int)g_map.player.pos.y; calculate_perpwalldist2(x, &sidedist, &deltadist, &step); - while (g_world_map[map_pos.x][map_pos.y] != 1) + while (map_get_case(&g_map, map_pos.x, map_pos.y)->wall == EMPTY) { if (sidedist.x < sidedist.y) { diff --git a/stream.c b/stream.c new file mode 100644 index 0000000..107c464 --- /dev/null +++ b/stream.c @@ -0,0 +1,89 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* stream.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/10/02 14:08:10 by mcolonna #+# #+# */ +/* Updated: 2024/10/02 17:31:34 by mcolonna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "stream.h" +#include + +void read_expected_string(const char *str, t_stream *stream, bool *err) +{ + int i; + + if (*err) + return ; + i = 0; + while (str[i]) + { + if (str[i] != stream->str[stream->i]) + { + *err = true; + return ; + } + i++; + stream->i++; + } + return ; +} + +/// @brief Check if a character is a digit. +/// @param c Character to check. +/// @return true if the character is a digit, false if not. +/// false if the character is '\0'. +static bool is_digit(char c) +{ + return (c >= '0' && c <= '9'); +} + +void read_unsigned(unsigned int *dest, t_stream *stream, bool *err) +{ + int r; + + if (*err) + return ; + if (!is_digit(stream->str[stream->i])) + { + *err = true; + return ; + } + r = 0; + while (is_digit(stream->str[stream->i])) + { + r = r * 10 + stream->str[stream->i] - '0'; + stream->i++; + } + *dest = r; +} + +void read_until(char c, char **dest, t_stream *stream, bool *err) +{ + int len; + int i; + + if (*err) + return ; + len = 0; + while (stream->str[stream->i + len] && stream->str[stream->i + len] != c) + len++; + *dest = malloc((len + 1) * sizeof(char)); + if (!*dest) + { + *err = true; + return ; + } + i = 0; + while (stream->str[stream->i] && stream->str[stream->i] != c) + { + (*dest)[i] = stream->str[stream->i]; + i++; + stream->i++; + } + (*dest)[i] = '\0'; +} diff --git a/stream.h b/stream.h new file mode 100644 index 0000000..741c4e2 --- /dev/null +++ b/stream.h @@ -0,0 +1,54 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* stream.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/10/02 12:33:25 by mcolonna #+# #+# */ +/* Updated: 2024/10/15 16:17:34 by mcolonna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef STREAM_H +# define STREAM_H + +# include + +/// @brief Represents a string and an associated cursor. +typedef struct s_stream +{ + /// @brief Index of the cursor. + int i; + + /// @brief Pointer to the string. + const char *str; +} t_stream; + +/// @brief Read a specific string, error if it isn't the expected string. +/// +/// @param str Expected string. +/// @param stream Stream to use. +/// @param err Set to true if an error occured. +/// If already true, the function won't do anything. +void read_expected_string(const char *str, t_stream *stream, bool *err); + +/// @brief Read an unsigned int (which fits the pattern /[0-9]+/). +/// +/// @param dest Will be set to the value of the unsigned integer. +/// @param stream Stream to use. +/// @param err Set to true if an error occured. +/// If already true, the function won't do anything. +void read_unsigned(unsigned int *dest, t_stream *stream, bool *err); + +/// @brief Read a string until limit char or \0. +/// +/// @param c Limit char. +/// @param dest Will be set to an alloc'd pointer to the read string. +/// NULL if alloc error. +/// @param stream Stream to use. +/// @param err Set to true if an error occured. +/// If already true, the function won't do anything. +void read_until(char c, char **dest, t_stream *stream, bool *err); + +#endif diff --git a/testmaps/err_doubleparameters.cub b/testmaps/err_doubleparameters.cub new file mode 100644 index 0000000..94251e8 --- /dev/null +++ b/testmaps/err_doubleparameters.cub @@ -0,0 +1,12 @@ +F 255,127,0 +EA eastimage +NO theimageforthenorthwall +C 0,2,67 +SO SOUTH!!!!!!1 +WE weeeee +SO south2 + +11111 +10N01 +10001 +11111 diff --git a/testmaps/err_extension.cud b/testmaps/err_extension.cud new file mode 100644 index 0000000..82b2ea9 --- /dev/null +++ b/testmaps/err_extension.cud @@ -0,0 +1,11 @@ +F 255,127,0 +EA eastimage +NO theimageforthenorthwall +C 0,2,67 +SO SOUTH!!!!!!1 +WE weeeee +1111111 +1000001 +10W0001 +1000001 +1111111 diff --git a/testmaps/err_nomapdescription.cub b/testmaps/err_nomapdescription.cub new file mode 100644 index 0000000..75bff64 --- /dev/null +++ b/testmaps/err_nomapdescription.cub @@ -0,0 +1,6 @@ +F 255,127,0 +EA eastimage +NO theimageforthenorthwall +C 0,2,67 +SO SOUTH!!!!!!1 +WE weeeee diff --git a/testmaps/err_nonclosed1.cub b/testmaps/err_nonclosed1.cub new file mode 100644 index 0000000..4cfef19 --- /dev/null +++ b/testmaps/err_nonclosed1.cub @@ -0,0 +1,11 @@ +F 255,127,0 +EA eastimage +NO theimageforthenorthwall +C 0,2,67 +SO SOUTH!!!!!!1 +WE weeeee +1101111 +1000001 +10W0001 +1000001 +1111111 diff --git a/testmaps/err_nonclosed2.cub b/testmaps/err_nonclosed2.cub new file mode 100644 index 0000000..64fd7c6 --- /dev/null +++ b/testmaps/err_nonclosed2.cub @@ -0,0 +1,11 @@ +F 255,127,0 +EA eastimage +NO theimageforthenorthwall +C 0,2,67 +SO SOUTH!!!!!!1 +WE weeeee +0111111 +1000001 +10W0001 +1000001 +1111111 diff --git a/testmaps/err_nonclosed3.cub b/testmaps/err_nonclosed3.cub new file mode 100644 index 0000000..d8e44be --- /dev/null +++ b/testmaps/err_nonclosed3.cub @@ -0,0 +1,11 @@ +F 255,127,0 +EA eastimage +NO theimageforthenorthwall +C 0,2,67 +SO SOUTH!!!!!!1 +WE weeeee + 111111 +1000001 +10W0001 +1000001 +1111111 diff --git a/testmaps/err_nonclosed4.cub b/testmaps/err_nonclosed4.cub new file mode 100644 index 0000000..536d61f --- /dev/null +++ b/testmaps/err_nonclosed4.cub @@ -0,0 +1,11 @@ +F 255,127,0 +EA eastimage +NO theimageforthenorthwall +C 0,2,67 +SO SOUTH!!!!!!1 +WE weeeee +1111111 +1000001 +10W0 01 +1000001 +1111111 diff --git a/testmaps/good.cub b/testmaps/good.cub new file mode 100644 index 0000000..82b2ea9 --- /dev/null +++ b/testmaps/good.cub @@ -0,0 +1,11 @@ +F 255,127,0 +EA eastimage +NO theimageforthenorthwall +C 0,2,67 +SO SOUTH!!!!!!1 +WE weeeee +1111111 +1000001 +10W0001 +1000001 +1111111 diff --git a/testmaps/good_directions.cub b/testmaps/good_directions.cub new file mode 100644 index 0000000..0701362 --- /dev/null +++ b/testmaps/good_directions.cub @@ -0,0 +1,13 @@ +F 255,127,0 +EA eastimage +NO theimageforthenorthwall +C 0,2,67 +SO SOUTH!!!!!!1 +WE weeeee + 111 +111110111 +10000N001 +111110111 + 101 + 101 + 111 diff --git a/testmaps/good_little.cub b/testmaps/good_little.cub new file mode 100644 index 0000000..7122765 --- /dev/null +++ b/testmaps/good_little.cub @@ -0,0 +1,9 @@ +F 255,127,0 +EA eastimage +NO theimageforthenorthwall +C 0,2,67 +SO SOUTH!!!!!!1 +WE weeeee +111 +1N1 +111 diff --git a/testmaps/good_weirdblank.cub b/testmaps/good_weirdblank.cub new file mode 100644 index 0000000..cf473b2 --- /dev/null +++ b/testmaps/good_weirdblank.cub @@ -0,0 +1,20 @@ +F 255,127,0 + +EA eastimage + +NO theimageforthenorthwall +C 0,2,67 + +SO SOUTH!!!!!!1 + +WE weeeee + + + + + +1111111 +1000001 +10W0001 +1000001 +1111111 diff --git a/testmaps/good_weirdshape.cub b/testmaps/good_weirdshape.cub new file mode 100644 index 0000000..edf7730 --- /dev/null +++ b/testmaps/good_weirdshape.cub @@ -0,0 +1,19 @@ +F 255,127,0 +EA eastimage +NO theimageforthenorthwall +C 0,2,67 +SO SOUTH!!!!!!1 +WE weeeee + + 111 + 111 101 + 111 101111101 + 101111101100001 + 100001101101111 + 1111111111101100101 + 1000000000101110101 +11011111110W00010101 +1001 10000010101 +1111 111111100000001111111 + 110000000000100000001 + 111111111111111111111 diff --git a/utils.c b/utils.c index 9af0d94..b43c3eb 100644 --- a/utils.c +++ b/utils.c @@ -6,14 +6,28 @@ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/10/15 12:38:40 by mcolonna #+# #+# */ -/* Updated: 2024/10/15 15:18:43 by mcolonna ### ########.fr */ +/* Updated: 2024/10/15 17:21:16 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ #include "algo.h" +#include void vector_from_rotation(t_point_double *vec, double angle, double norm) { vec->x = -cos(angle) * norm; vec->y = sin(angle) * norm; } + +void write_err(const char *str, ...) +{ + va_list args; + + va_start(args, str); + write(2, "Error\n", 6); + while (str) + { + write(2, str, ft_strlen(str)); + str = va_arg(args, const char *); + } +} diff --git a/utils.h b/utils.h new file mode 100644 index 0000000..ccca448 --- /dev/null +++ b/utils.h @@ -0,0 +1,44 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* utils.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/10/15 16:56:47 by mcolonna #+# #+# */ +/* Updated: 2024/10/15 17:21:10 by mcolonna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef UTILS_H +# define UTILS_H + +# include + +typedef struct s_point_double +{ + double x; + double y; +} t_point_double; + +typedef struct s_point_int +{ + int x; + int y; +} t_point_int; + +// TODO Must the transparency be 0 or 255? +/// @brief Represents an TRGB color in 0xTTRRGGBB format. +typedef __u32 t_color; + +/// @brief Convert a color from each color value to a t_color. +/// +/// @param red Level of red from 0 to 255. +/// @param green Level of green from 0 to 255. +/// @param blue Level of blue from 0 to 255. +/// @return The result. +t_color color_from_rgb(int red, int green, int blue); + +void write_err(const char *str, ...); + +#endif