merge map parsing with expose
This commit is contained in:
commit
d1f2136b13
35 changed files with 1364 additions and 152 deletions
98
Makefile
98
Makefile
|
@ -1,45 +1,71 @@
|
|||
# **************************************************************************** #
|
||||
# #
|
||||
# ::: :::::::: #
|
||||
# Makefile :+: :+: :+: #
|
||||
# +:+ +:+ +:+ #
|
||||
# By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ #
|
||||
# +#+#+#+#+#+ +#+ #
|
||||
# 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)
|
||||
|
|
56
algo.c
56
algo.c
|
@ -6,52 +6,16 @@
|
|||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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 <map.cub>\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);
|
||||
|
|
37
algo.h
37
algo.h
|
@ -6,7 +6,7 @@
|
|||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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 <unistd.h>
|
||||
# include <math.h>
|
||||
# include <linux/types.h>
|
||||
# include <stdbool.h>
|
||||
# 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);
|
||||
|
|
18
color.c
Normal file
18
color.c
Normal file
|
@ -0,0 +1,18 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* color.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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);
|
||||
}
|
23
dev/cub.vim
Normal file
23
dev/cub.vim
Normal file
|
@ -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()
|
134
map.h
Normal file
134
map.h
Normal file
|
@ -0,0 +1,134 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* map.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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 <stdbool.h>
|
||||
# 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
|
123
map1.c
Normal file
123
map1.c
Normal file
|
@ -0,0 +1,123 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* map1.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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 <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
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);
|
||||
}
|
27
map2.c
Normal file
27
map2.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* map2.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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 <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
const t_map_case *map_get_case(const t_map *map, int x, int y)
|
||||
{
|
||||
return (&map->cases[y * map->width + x]);
|
||||
}
|
25
map_mapping.c
Normal file
25
map_mapping.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* map_mapping.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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 <stdlib.h>
|
||||
|
||||
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}}}};
|
31
map_mapping.h
Normal file
31
map_mapping.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* map_mapping.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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
|
83
map_utils.h
Normal file
83
map_utils.h
Normal file
|
@ -0,0 +1,83 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* map_utils.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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 <stdbool.h>
|
||||
# include <stddef.h>
|
||||
|
||||
/// @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
|
135
map_utils1.c
Normal file
135
map_utils1.c
Normal file
|
@ -0,0 +1,135 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* map_utils1.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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 <stdlib.h>
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
105
map_utils2.c
Normal file
105
map_utils2.c
Normal file
|
@ -0,0 +1,105 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* map_utils2.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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 <stdlib.h>
|
||||
|
||||
/// @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);
|
||||
}
|
56
move.c
56
move.c
|
@ -6,53 +6,35 @@
|
|||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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);
|
||||
|
|
46
player.c
Normal file
46
player.c
Normal file
|
@ -0,0 +1,46 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* player.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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);
|
||||
}
|
23
player.h
Normal file
23
player.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* player.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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
|
95
read_all_text.c
Normal file
95
read_all_text.c
Normal file
|
@ -0,0 +1,95 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* read_all_text.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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 <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/// @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));
|
||||
}
|
29
read_all_text.h
Normal file
29
read_all_text.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* read_all_text.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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
|
24
render.c
24
render.c
|
@ -6,7 +6,7 @@
|
|||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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)
|
||||
{
|
||||
|
|
89
stream.c
Normal file
89
stream.c
Normal file
|
@ -0,0 +1,89 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* stream.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2024/10/02 14:08:10 by mcolonna #+# #+# */
|
||||
/* Updated: 2024/10/02 17:31:34 by mcolonna ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "stream.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
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';
|
||||
}
|
54
stream.h
Normal file
54
stream.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* stream.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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 <stdbool.h>
|
||||
|
||||
/// @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
|
12
testmaps/err_doubleparameters.cub
Normal file
12
testmaps/err_doubleparameters.cub
Normal file
|
@ -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
|
11
testmaps/err_extension.cud
Normal file
11
testmaps/err_extension.cud
Normal file
|
@ -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
|
6
testmaps/err_nomapdescription.cub
Normal file
6
testmaps/err_nomapdescription.cub
Normal file
|
@ -0,0 +1,6 @@
|
|||
F 255,127,0
|
||||
EA eastimage
|
||||
NO theimageforthenorthwall
|
||||
C 0,2,67
|
||||
SO SOUTH!!!!!!1
|
||||
WE weeeee
|
11
testmaps/err_nonclosed1.cub
Normal file
11
testmaps/err_nonclosed1.cub
Normal file
|
@ -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
|
11
testmaps/err_nonclosed2.cub
Normal file
11
testmaps/err_nonclosed2.cub
Normal file
|
@ -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
|
11
testmaps/err_nonclosed3.cub
Normal file
11
testmaps/err_nonclosed3.cub
Normal file
|
@ -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
|
11
testmaps/err_nonclosed4.cub
Normal file
11
testmaps/err_nonclosed4.cub
Normal file
|
@ -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
|
11
testmaps/good.cub
Normal file
11
testmaps/good.cub
Normal file
|
@ -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
|
13
testmaps/good_directions.cub
Normal file
13
testmaps/good_directions.cub
Normal file
|
@ -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
|
9
testmaps/good_little.cub
Normal file
9
testmaps/good_little.cub
Normal file
|
@ -0,0 +1,9 @@
|
|||
F 255,127,0
|
||||
EA eastimage
|
||||
NO theimageforthenorthwall
|
||||
C 0,2,67
|
||||
SO SOUTH!!!!!!1
|
||||
WE weeeee
|
||||
111
|
||||
1N1
|
||||
111
|
20
testmaps/good_weirdblank.cub
Normal file
20
testmaps/good_weirdblank.cub
Normal file
|
@ -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
|
19
testmaps/good_weirdshape.cub
Normal file
19
testmaps/good_weirdshape.cub
Normal file
|
@ -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
|
16
utils.c
16
utils.c
|
@ -6,14 +6,28 @@
|
|||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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 <stdarg.h>
|
||||
|
||||
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 *);
|
||||
}
|
||||
}
|
||||
|
|
44
utils.h
Normal file
44
utils.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* utils.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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 <linux/types.h>
|
||||
|
||||
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
|
Loading…
Add table
Reference in a new issue