From af747497060d8a311204ec58b3ac87cc585462fc Mon Sep 17 00:00:00 2001 From: Charles Date: Wed, 5 Feb 2020 01:29:44 +0100 Subject: better parsing --- include/cub3d.h | 19 +++++++-- libft | 2 +- minimalist.cub | 40 +++++-------------- src/error.c | 2 +- src/event.c | 21 +++++++--- src/helper.c | 2 +- src/main.c | 44 +-------------------- src/parse/parse.c | 48 +++++++++------------- src/parse/parse_check.c | 14 ++++--- src/parse/parse_color.c | 8 +++- src/parse/parse_file.c | 38 +++++++++++++++++- src/parse/parse_resolution.c | 5 ++- src/parse/parse_textures.c | 17 +++++++- src/render.c | 2 +- src/render_sprite.c | 94 ++++++++++++++++++++++++++++++-------------- src/render_state.c | 2 +- src/sprite_sort.c | 2 +- src/state.c | 43 ++++++++++---------- src/texture.c | 8 ++-- test.cub | 21 +++++++--- 20 files changed, 244 insertions(+), 188 deletions(-) diff --git a/include/cub3d.h b/include/cub3d.h index eed376c..bd696fb 100644 --- a/include/cub3d.h +++ b/include/cub3d.h @@ -6,7 +6,7 @@ /* By: cacharle +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2019/11/15 06:40:37 by cacharle #+# #+# */ -/* Updated: 2020/02/04 04:09:56 by cacharle ### ########.fr */ +/* Updated: 2020/02/05 01:19:02 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ #include @@ -103,8 +103,19 @@ typedef struct double dist; } t_sprite; +typedef unsigned short t_pflags; +# define PFLAGS_R (1 << 0) +# define PFLAGS_NO (1 << 1) +# define PFLAGS_SO (1 << 2) +# define PFLAGS_WE (1 << 3) +# define PFLAGS_EA (1 << 4) +# define PFLAGS_S (1 << 5) +# define PFLAGS_F (1 << 6) +# define PFLAGS_C (1 << 7) + typedef struct s_state { + t_pflags pflags; t_bool running; void *mlx_ptr; void *window_ptr; @@ -175,13 +186,15 @@ typedef struct s_option_parser t_state *parse(char *filename); t_bool parse_line(t_state *state, char *line); t_state *parse_map(t_state *state, char **lines); -t_cell *create_map_row(char *line); +t_cell *create_map_row(t_state *state, char *line); /* ** parse/parse_file.c */ char **get_file_lines(char *filename); +int parse_premap(t_state *state, char **lines); +t_bool create_map_row_char(char c, t_cell *row, int i); /* ** parse/parse_check.c @@ -227,7 +240,7 @@ t_state *state_new(t_state *state); void state_init_player(t_state *state); t_state *state_new_empty(void); void *state_destroy(t_state *state); -void load_texture(void *mlx_ptr, t_image *image, char *path); +t_bool state_init_textures(t_state *state); /* ** render.c diff --git a/libft b/libft index f078f19..19964c7 160000 --- a/libft +++ b/libft @@ -1 +1 @@ -Subproject commit f078f191515d0fc65340a8722fad14f3de679d7b +Subproject commit 19964c7a382bcc5c0f09b1233b54b559c44e3a28 diff --git a/minimalist.cub b/minimalist.cub index 24a1db0..03690a5 100644 --- a/minimalist.cub +++ b/minimalist.cub @@ -1,45 +1,23 @@ - - - -R 200 200 - -NO ./textures/greystone.xpm - - - +R 1600 1200 +NO ./textures/eagle.xpm SO ./textures/greystone.xpm - - - - -WE ./textures/greystone.xpm - - +WE ./textures/wood.xpm EA ./textures/greystone.xpm - - - - -S ./textures/cacharle.xpm - - - - -F 10,10,10 -C 40,40,40 +S ./textures/cheese.xpm +F 10,10,10 +C 40,40,40 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 1 1 1 1 1 0 0 0 0 0 2 0 0 0 1 1 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 1 1 1 0 0 0 0 0 0 2 0 0 0 0 0 1 0 0 0 1 - -1 2 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 0 1 0 0 0 1 1 0 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 1 1 0 1 1 1 1 0 2 0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 1 1 1 0 0 0 0 0 0 1 0 0 0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 1 1 1 0 1 0 1 0 0 1 0 0 0 1 1 1 0 0 0 0 0 0 1 1 0 1 0 1 0 1 1 1 0 0 0 0 0 0 1 0 0 0 1 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 1 0 0 1 0 N 0 1 -1 1 0 0 0 0 0 0 1 1 0 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 0 0 1 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 1 0 0 1 0 0 0 1 +1 1 0 0 0 0 0 0 1 1 0 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 N 0 1 1 1 1 1 0 1 1 1 1 1 1 1 0 1 0 1 1 1 1 1 0 1 1 1 1 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 1 1 1 1 1 diff --git a/src/error.c b/src/error.c index 03352e1..7d280d5 100644 --- a/src/error.c +++ b/src/error.c @@ -6,7 +6,7 @@ /* By: cacharle +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/01/11 13:33:14 by cacharle #+# #+# */ -/* Updated: 2020/02/04 02:17:53 by cacharle ### ########.fr */ +/* Updated: 2020/02/05 00:58:08 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/event.c b/src/event.c index 5a5b3e1..c91b204 100644 --- a/src/event.c +++ b/src/event.c @@ -6,16 +6,25 @@ /* By: cacharle +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2019/11/15 06:39:37 by cacharle #+# #+# */ -/* Updated: 2020/02/03 00:44:39 by cacharle ### ########.fr */ +/* Updated: 2020/02/04 23:50:51 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ #include "cub3d.h" -#define ROTATE_STEP (M_PI / 20.0) -#define MOVE_SPEED 0.24 +#define ROTATE_STEP (M_PI / 12.0) +#define MOVE_SPEED 0.40 -int event_keydown(int key, t_state *state) +static t_bool valid_pos(t_state *state) +{ + return (state->pos.x > 0 && state->pos.y > 0 + && state->pos.x < (double)(state->map_width - 1) + && state->pos.y < (double)(state->map_height - 1) + && state->map[(int)state->pos.y][(int)state->pos.x] != CELL_WALL + && state->map[(int)state->pos.y][(int)state->pos.x] != CELL_ITEM); +} + +int event_keydown(int key, t_state *state) { t_vector saved_pos; @@ -38,12 +47,12 @@ int event_keydown(int key, t_state *state) helper_rotate_player(state, -ROTATE_STEP); else if (key == MLXK_RIGHT) helper_rotate_player(state, ROTATE_STEP); - if (state->map[(int)state->pos.y][(int)state->pos.x] == CELL_WALL) + if (!valid_pos(state)) state->pos = saved_pos; return (0); } -int event_quit(t_state *state) +int event_quit(t_state *state) { state->running = FALSE; return (0); diff --git a/src/helper.c b/src/helper.c index ca0f879..1197f03 100644 --- a/src/helper.c +++ b/src/helper.c @@ -6,7 +6,7 @@ /* By: cacharle +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/01/11 07:32:20 by cacharle #+# #+# */ -/* Updated: 2020/02/04 02:17:38 by cacharle ### ########.fr */ +/* Updated: 2020/02/04 20:00:23 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/main.c b/src/main.c index f1d4f20..b935b52 100644 --- a/src/main.c +++ b/src/main.c @@ -6,7 +6,7 @@ /* By: cacharle +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2019/11/15 06:39:39 by cacharle #+# #+# */ -/* Updated: 2020/02/04 05:29:40 by cacharle ### ########.fr */ +/* Updated: 2020/02/05 00:14:18 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -28,45 +28,3 @@ int main(int argc, char **argv) mlx_loop(state->mlx_ptr); return (0); } - -/* */ -/* int main(int argc, char **argv) */ -/* { */ -/* (void)argc; */ -/* t_state *s = parse_check(parse(argv[1])); */ -/* if (s == NULL) */ -/* return (1); */ -/* printf("R %d %d\n", s->window.width, s->window.height); */ -/* printf("NO |%s|\n", s->textures_path[TEX_NORTH]); */ -/* printf("SO |%s|\n", s->textures_path[TEX_SOUTH]); */ -/* printf("WE |%s|\n", s->textures_path[TEX_WEST]); */ -/* printf("EA |%s|\n\n", s->textures_path[TEX_EAST]); */ -/* printf("S |%s|\n", s->textures_path[TEX_SPRITE]); */ -/* printf("F %d,%d,%d\n", s->floor_color.rgb.r, s->floor_color.rgb.g, s->floor_color.rgb.b); */ -/* printf("C %d,%d,%d\n\n", s->ceilling_color.rgb.r, s->ceilling_color.rgb.g, s->ceilling_color.rgb.b); */ -/* printf("%dx%d\n", s->map_height, s->map_width); */ -/* for (int i = 0; i < s->map_height; i++) */ -/* { */ -/* for (int j = 0; j < s->map_width; j++) */ -/* { */ -/* if (s->map[i][j] == CELL_WALL) */ -/* printf("#"); */ -/* else if (s->map[i][j] == CELL_EMPTY) */ -/* printf(" "); */ -/* else */ -/* printf("%d", s->map[i][j]); */ -/* if (j != s->map_width - 1) */ -/* printf(" "); */ -/* } */ -/* printf("\n"); */ -/* } */ -/* printf("post state_new\n"); */ -/* #<{(| if ((s = state_new(s)) == NULL) |)}># */ -/* #<{(| { |)}># */ -/* #<{(| printf("Error: state new"); |)}># */ -/* #<{(| return 1; |)}># */ -/* #<{(| } |)}># */ -/* #<{(| printf("state->pos [%f %f]\n", s->pos.x, s->pos.y); |)}># */ -/* #<{(| state_destroy(s); |)}># */ -/* return 0; */ -/* } */ diff --git a/src/parse/parse.c b/src/parse/parse.c index 4c51945..c1f1a5f 100644 --- a/src/parse/parse.c +++ b/src/parse/parse.c @@ -6,7 +6,7 @@ /* By: cacharle +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2019/11/15 09:29:21 by cacharle #+# #+# */ -/* Updated: 2020/02/04 04:41:26 by cacharle ### ########.fr */ +/* Updated: 2020/02/05 01:27:22 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -22,19 +22,15 @@ t_state *parse(char *filename) return (error_put_return("create empty state")); if ((lines = get_file_lines(filename)) == NULL) return (error_put_return_state_destroy("read .cub file", state)); - i = -1; - while (lines[++i] != NULL) + if ((i = parse_premap(state, lines)) == -1) { - if (*lines[i] == '1') - break ; - if (!parse_line(state, lines[i])) - return (error_put_return_lines_state_destroy( - "parse configuration", state, lines)); + return (error_put_return_lines_state_destroy( + "parse option", state, lines)); } - if ((state = parse_map(state, lines + i)) == NULL) + if (state->pflags != 0xFF || (state = parse_map(state, lines + i)) == NULL) { - return (error_put_return_lines_state_destroy("parse map", - state, lines)); + return (error_put_return_lines_state_destroy(state == NULL ? + "parse map" : "parse options", state, lines)); } helper_free_splited(lines); return (state); @@ -54,15 +50,14 @@ static t_option_parser g_option_parsers[] = t_bool parse_line(t_state *state, char *line) { - int i; - char *tmp; + int i; + char *tmp; if (!*line) return (TRUE); i = -1; while (++i < (int)(sizeof(g_option_parsers) / sizeof(t_option_parser))) { - if (ft_strncmp(g_option_parsers[i].id, line, ft_strlen(g_option_parsers[i].id)) == 0) { @@ -84,37 +79,27 @@ t_state *parse_map(t_state *state, char **lines) if (*lines[i] != '1') return (NULL); state->map_height = i; - if ((state->map = (t_map)malloc(sizeof(t_cell*) * i)) == NULL) + if ((state->map = (t_map)ft_calloc(i, sizeof(t_cell*))) == NULL) return (NULL); state->map_width = ft_strcount(*lines, '1'); i = -1; while (lines[++i] != NULL) - if ((state->map[i] = create_map_row(lines[i])) == NULL) + if ((state->map[i] = create_map_row(state, lines[i])) == NULL) return (NULL); return (state); } -t_cell *create_map_row(char *line) +t_cell *create_map_row(t_state *state, char *line) { int i; t_cell *row; - if ((row = (t_cell*)malloc(sizeof(t_cell) * ft_strlen(line))) == NULL) + if ((row = (t_cell*)malloc(sizeof(t_cell) * state->map_width)) == NULL) return (NULL); i = 0; while (*line) { - if (*line == '0' || *line == '1' || *line == '2') - row[i++] = *line - '0'; - else if (*line == 'N') - row[i++] = CELL_LOOK_NORTH; - else if (*line == 'S') - row[i++] = CELL_LOOK_SOUTH; - else if (*line == 'W') - row[i++] = CELL_LOOK_WEST; - else if (*line == 'E') - row[i++] = CELL_LOOK_EAST; - else + if (!create_map_row_char(*line, row, i++)) { free(row); return (NULL); @@ -123,5 +108,10 @@ t_cell *create_map_row(char *line) while (*line == ' ') line++; } + if (i != state->map_width) + { + free(row); + return (NULL); + } return (row); } diff --git a/src/parse/parse_check.c b/src/parse/parse_check.c index 976020b..09a2429 100644 --- a/src/parse/parse_check.c +++ b/src/parse/parse_check.c @@ -6,7 +6,7 @@ /* By: cacharle +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/01/11 10:59:15 by cacharle #+# #+# */ -/* Updated: 2020/02/04 05:07:22 by cacharle ### ########.fr */ +/* Updated: 2020/02/04 18:49:49 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -27,7 +27,12 @@ static t_bool check_player_count(t_state *state) if (helper_is_player_cell(state->map[i][j])) player_count++; } - return (player_count == 1); + if (player_count != 1) + { + error_put("validate map with other than one player"); + return (FALSE); + } + return (TRUE); } t_state *parse_check(t_state *state) @@ -53,9 +58,6 @@ t_state *parse_check(t_state *state) "validate map without borders", state)); } if (!check_player_count(state)) - { - return (error_put_return_state_destroy( - "validate map with other than one player", state)); - } + return (state_destroy(state)); return (state); } diff --git a/src/parse/parse_color.c b/src/parse/parse_color.c index d3cee05..b939076 100644 --- a/src/parse/parse_color.c +++ b/src/parse/parse_color.c @@ -6,7 +6,7 @@ /* By: cacharle +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/01/11 09:52:34 by cacharle #+# #+# */ -/* Updated: 2020/02/04 05:12:42 by cacharle ### ########.fr */ +/* Updated: 2020/02/05 00:04:53 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,6 +16,8 @@ t_bool parse_ceilling_color(t_state *state, char *line) { long tmp; + if (state->pflags & PFLAGS_C) + return (FALSE); errno = 0; state->ceilling_color.hexcode = 0x0; if ((tmp = ft_strtol(line, &line, 10)) > 255 || tmp < 0) @@ -33,6 +35,7 @@ t_bool parse_ceilling_color(t_state *state, char *line) state->ceilling_color.rgb.b = (t_byte)tmp; if (errno != 0) return (FALSE); + state->pflags |= PFLAGS_C; return (TRUE); } @@ -40,6 +43,8 @@ t_bool parse_floor_color(t_state *state, char *line) { long tmp; + if (state->pflags & PFLAGS_F) + return (FALSE); errno = 0; state->floor_color.hexcode = 0x0; if ((tmp = ft_strtol(line, &line, 10)) > 255 || tmp < 0) @@ -57,5 +62,6 @@ t_bool parse_floor_color(t_state *state, char *line) state->floor_color.rgb.b = (t_byte)tmp; if (errno != 0) return (FALSE); + state->pflags |= PFLAGS_F; return (TRUE); } diff --git a/src/parse/parse_file.c b/src/parse/parse_file.c index 443a1b5..8c6ef5e 100644 --- a/src/parse/parse_file.c +++ b/src/parse/parse_file.c @@ -6,7 +6,7 @@ /* By: cacharle +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/02/04 03:50:53 by cacharle #+# #+# */ -/* Updated: 2020/02/04 04:28:41 by cacharle ### ########.fr */ +/* Updated: 2020/02/05 01:27:26 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -49,5 +49,39 @@ char **get_file_lines(char *filename) if (ret == -1) return (NULL); close(fd); - return (trim_file_lines(ft_split(file, '\n'))); + return (trim_file_lines(ft_split_strict(file, '\n'))); +} + +int parse_premap(t_state *state, char **lines) +{ + int i; + + i = -1; + while (lines[++i] != NULL) + { + if (*lines[i] == '\n') + continue ; + if (*lines[i] == '1') + break ; + if (!parse_line(state, lines[i])) + return (-1); + } + return (i); +} + +t_bool create_map_row_char(char c, t_cell *row, int i) +{ + if (c == '0' || c == '1' || c == '2') + row[i] = c - '0'; + else if (c == 'N') + row[i] = CELL_LOOK_NORTH; + else if (c == 'S') + row[i] = CELL_LOOK_SOUTH; + else if (c == 'W') + row[i] = CELL_LOOK_WEST; + else if (c == 'E') + row[i] = CELL_LOOK_EAST; + else + return (FALSE); + return (TRUE); } diff --git a/src/parse/parse_resolution.c b/src/parse/parse_resolution.c index 300b461..b863c94 100644 --- a/src/parse/parse_resolution.c +++ b/src/parse/parse_resolution.c @@ -6,7 +6,7 @@ /* By: cacharle +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2019/11/15 09:29:27 by cacharle #+# #+# */ -/* Updated: 2020/02/04 04:40:35 by cacharle ### ########.fr */ +/* Updated: 2020/02/05 00:04:03 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -20,6 +20,8 @@ t_bool parse_resolution(t_state *state, char *line) { long tmp; + if (state->pflags & PFLAGS_R) + return (FALSE); errno = 0; if ((tmp = ft_strtol(line, &line, 10)) < MIN_RES) return (FALSE); @@ -37,5 +39,6 @@ t_bool parse_resolution(t_state *state, char *line) state->window.height = tmp; if (*line != '\0' || errno != 0 || state->window.height > 2160) return (FALSE); + state->pflags |= PFLAGS_R; return (TRUE); } diff --git a/src/parse/parse_textures.c b/src/parse/parse_textures.c index f6ba1a0..e048bd5 100644 --- a/src/parse/parse_textures.c +++ b/src/parse/parse_textures.c @@ -6,7 +6,7 @@ /* By: cacharle +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/01/11 09:47:53 by cacharle #+# #+# */ -/* Updated: 2020/02/02 19:21:39 by cacharle ### ########.fr */ +/* Updated: 2020/02/05 00:06:18 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,35 +14,50 @@ t_bool parse_north_texture(t_state *state, char *line) { + if (state->pflags & PFLAGS_NO) + return (FALSE); if ((state->textures_path[TEX_NORTH] = ft_strdup(line)) == NULL) return (FALSE); + state->pflags |= PFLAGS_NO; return (TRUE); } t_bool parse_south_texture(t_state *state, char *line) { + if (state->pflags & PFLAGS_SO) + return (FALSE); if ((state->textures_path[TEX_SOUTH] = ft_strdup(line)) == NULL) return (FALSE); + state->pflags |= PFLAGS_SO; return (TRUE); } t_bool parse_west_texture(t_state *state, char *line) { + if (state->pflags & PFLAGS_WE) + return (FALSE); if ((state->textures_path[TEX_WEST] = ft_strdup(line)) == NULL) return (FALSE); + state->pflags |= PFLAGS_WE; return (TRUE); } t_bool parse_east_texture(t_state *state, char *line) { + if (state->pflags & PFLAGS_EA) + return (FALSE); if ((state->textures_path[TEX_EAST] = ft_strdup(line)) == NULL) return (FALSE); + state->pflags |= PFLAGS_EA; return (TRUE); } t_bool parse_sprite_texture(t_state *state, char *line) { + if (state->pflags & PFLAGS_S) + return (FALSE); if ((state->textures_path[TEX_SPRITE] = ft_strdup(line)) == NULL) return (FALSE); + state->pflags |= PFLAGS_S; return (TRUE); } diff --git a/src/render.c b/src/render.c index de7e843..e6c7eeb 100644 --- a/src/render.c +++ b/src/render.c @@ -6,7 +6,7 @@ /* By: cacharle +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/01/11 13:37:17 by cacharle #+# #+# */ -/* Updated: 2020/02/04 02:31:57 by cacharle ### ########.fr */ +/* Updated: 2020/02/04 23:16:38 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/render_sprite.c b/src/render_sprite.c index 379f67a..2ca34c0 100644 --- a/src/render_sprite.c +++ b/src/render_sprite.c @@ -6,47 +6,80 @@ /* By: cacharle +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/02/02 17:39:07 by cacharle #+# #+# */ -/* Updated: 2020/02/04 03:38:53 by cacharle ### ########.fr */ +/* Updated: 2020/02/04 23:25:21 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ #include "cub3d.h" +/* +** 1: While raycasting the walls, store the perpendicular distance +** of each vertical stripe in a 1D ZBuffer +** 2: Calculate the distance of each sprite to the player +** 3: Use this distance to sort the sprites, from furthest away +** to closest to the camera +** 4: Project the sprite on the camera plane (in 2D): +** subtract the player position from the sprite position, +** then multiply the result with the inverse of the 2x2 camera matrix +** 5: Calculate the size of the sprite on the screen +** (both in x and y direction) by using the perpendicular distance +** 6: Draw the sprites vertical stripe by vertical stripe, +** don't draw the vertical stripe if the distance is further away +** than the 1D ZBuffer of the walls of the current stripe +** 7: Draw the vertical stripe pixel by pixel, make sure there's +** an invisible color or all sprites would be rectangles +*/ + +static void draw_stripe_pixels(t_state *state, t_sprite_state *sstate, + int stripe, int tex_x) +{ + int y; + int d; + int tex_y; + t_color color; + + y = sstate->draw_start - 1; + while (++y < sstate->draw_end_y) + { + d = y * 256 - state->window.height * 128 + sstate->sprite_height * 128; + tex_y = (d * state->textures[TEX_SPRITE].height) + / (sstate->sprite_height * 256); + color = ((t_color*)state->textures[TEX_SPRITE].data) + [state->textures[TEX_SPRITE].width * tex_y + tex_x]; + if ((color.hexcode & 0x00FFFFFF) != 0) + ((t_color*)state->window.data)[y * state->window.width + stripe] = + color; + } +} + static void draw_stripe(t_state *state, t_sprite_state *sstate, int stripe) { int tex_width; int tex_height; int tex_x; - int y; tex_width = state->textures[TEX_SPRITE].width; tex_height = state->textures[TEX_SPRITE].height; - tex_x = (int)(256 * (stripe - (-sstate->sprite_width / 2 + sstate->sprite_window_x)) - * tex_width / sstate->sprite_width) / 256; - if (!(sstate->transform.y > 0 && stripe > 0 && stripe < state->window.width && sstate->transform.y < state->z_buffer[stripe])) + tex_x = (int)(256 * (stripe - (-sstate->sprite_width / 2 + + sstate->sprite_window_x)) + * tex_width / sstate->sprite_width) / 256; + if (!(sstate->transform.y > 0 && stripe > 0 && stripe < state->window.width + && sstate->transform.y < state->z_buffer[stripe])) return ; - y = sstate->draw_start - 1; - while (++y < sstate->draw_end_y) - { - int d = y * 256 - state->window.height * 128 + sstate->sprite_height * 128; - int tex_y = ((d * tex_height) / sstate->sprite_height) / 256; - t_color color = ((t_color*)state->textures[TEX_SPRITE].data)[tex_width * tex_y + tex_x]; - if ((color.hexcode & 0x00FFFFFF) != 0) - ((t_color*)state->window.data)[y * state->window.width + stripe] = color; - } + draw_stripe_pixels(state, sstate, stripe, tex_x); } -static void sprite_boundary(t_state *state, t_sprite_state *sstate) +static void sprite_boundary(t_state *state, t_sprite_state *sstate) { sstate->sprite_height = ft_abs((int)(state->window.height / (sstate->transform.y))); sstate->draw_start = -sstate->sprite_height / 2 + state->window.height / 2; - if(sstate->draw_start < 0) + if (sstate->draw_start < 0) sstate->draw_start = 0; sstate->draw_end_y = sstate->sprite_height / 2 + state->window.height / 2; - if(sstate->draw_end_y >= state->window.height) + if (sstate->draw_end_y >= state->window.height) sstate->draw_end_y = state->window.height - 1; - sstate->sprite_width = ft_abs( (int) (state->window.height + sstate->sprite_width = ft_abs((int)(state->window.height / (sstate->transform.y))); sstate->draw_start_x = -sstate->sprite_width / 2 + sstate->sprite_window_x; if (sstate->draw_start_x < 0) @@ -56,28 +89,29 @@ static void sprite_boundary(t_state *state, t_sprite_state *sstate) sstate->draw_end_x = state->window.width - 1; } -static void render_sprite(t_state *state, int i) +static void render_sprite(t_state *state, int i) { int stripe; t_sprite_state sstate; + double inverse_det; + t_vector sprite; - sstate.sprite.x = state->sprites[i].pos.x - state->pos.x; - sstate.sprite.y = state->sprites[i].pos.y - state->pos.y; - sstate.inverse_det = 1.0 / (state->plane.x - * state->dir.y - state->dir.x * state->plane.y); - sstate.transform.x = sstate.inverse_det - * (state->dir.y * sstate.sprite.x - state->dir.x * sstate.sprite.y); - sstate.transform.y = sstate.inverse_det * (-state->plane.y - * sstate.sprite.x + state->plane.x * sstate.sprite.y); - sstate.sprite_window_x = (int)((state->window.width / 2) - * (1 + sstate.transform.x / sstate.transform.y)); + sprite = vector_add(state->sprites[i].pos, vector_scale(state->pos, -1.0)); + inverse_det = 1.0 / (state->plane.x * state->dir.y + - state->dir.x * state->plane.y); + sstate.transform.x = state->dir.y * sprite.x - state->dir.x * sprite.y; + sstate.transform.y = + -state->plane.y * sprite.x + state->plane.x * sprite.y; + sstate.transform = vector_scale(sstate.transform, inverse_det); + sstate.sprite_window_x = (int)((state->window.width / 2.0) + * (1.0 + sstate.transform.x / sstate.transform.y)); sprite_boundary(state, &sstate); stripe = sstate.draw_start_x - 1; while (++stripe < sstate.draw_end_x) draw_stripe(state, &sstate, stripe); } -void render_update_sprite(t_state *state) +void render_update_sprite(t_state *state) { int i; diff --git a/src/render_state.c b/src/render_state.c index 09f6f0c..5d535d2 100644 --- a/src/render_state.c +++ b/src/render_state.c @@ -6,7 +6,7 @@ /* By: cacharle +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/01/15 14:40:14 by cacharle #+# #+# */ -/* Updated: 2020/02/04 02:09:43 by cacharle ### ########.fr */ +/* Updated: 2020/02/04 18:30:10 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/sprite_sort.c b/src/sprite_sort.c index 4227743..553df43 100644 --- a/src/sprite_sort.c +++ b/src/sprite_sort.c @@ -6,7 +6,7 @@ /* By: cacharle +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/02/04 02:35:05 by cacharle #+# #+# */ -/* Updated: 2020/02/04 03:38:15 by cacharle ### ########.fr */ +/* Updated: 2020/02/04 23:20:37 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/state.c b/src/state.c index 414c2f1..ba46647 100644 --- a/src/state.c +++ b/src/state.c @@ -6,7 +6,7 @@ /* By: cacharle +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2019/11/19 16:39:57 by cacharle #+# #+# */ -/* Updated: 2020/02/04 03:37:21 by cacharle ### ########.fr */ +/* Updated: 2020/02/05 01:28:31 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -18,8 +18,6 @@ t_state *state_new(t_state *state) { - int i; - if (state == NULL) return (NULL); state->running = TRUE; @@ -28,15 +26,8 @@ t_state *state_new(t_state *state) if ((state->window_ptr = mlx_new_window(state->mlx_ptr, state->window.width, state->window.height, WINDOW_TITLE)) == NULL) return (state_destroy(state)); - i = -1; - while (++i < TEXTURES_NUM) - { - puts(state->textures_path[i]); - load_texture(state->mlx_ptr, &state->textures[i], - state->textures_path[i]); - if (state->textures[i].id == NULL) - return (error_put_return_state_destroy("load texture", state)); - } + if (!state_init_textures(state)) + return (error_put_return_state_destroy("load texture", state)); if ((state->window.id = mlx_new_image(state->mlx_ptr, state->window.width, state->window.height)) == NULL) return (state_destroy(state)); @@ -44,7 +35,8 @@ t_state *state_new(t_state *state) &state->window.depth, &state->window.size_line, &state->window.endian); state_init_player(state); - if ((state->z_buffer = malloc(sizeof(double) * state->window.width)) == NULL) + if ((state->z_buffer = malloc(sizeof(double) + * state->window.width)) == NULL) return (error_put_return_state_destroy("create z buffer", state)); if (!state_init_sprites(state)) return (error_put_return_state_destroy("create sprites pos", state)); @@ -119,16 +111,27 @@ void *state_destroy(t_state *state) while (state->map_height-- > 0 && state->map[state->map_height] != NULL) free(state->map[state->map_height]); free(state->map); - printf("===free state\n"); free(state); return (NULL); } -void load_texture(void *mlx_ptr, t_image *image, char *path) +t_bool state_init_textures(t_state *state) { - if ((image->id = mlx_xpm_file_to_image( - mlx_ptr, path, &image->width, &image->height)) == NULL) - return ; - image->data = mlx_get_data_addr(image->id, &image->depth, - &image->size_line, &image->endian); + int i; + t_image *tex; + + i = -1; + while (++i < TEXTURES_NUM) + { + tex = &state->textures[i]; + if ((tex->id = mlx_xpm_file_to_image(state->mlx_ptr, + state->textures_path[i], &tex->width, &tex->height)) + == NULL) + return (FALSE); + tex->data = mlx_get_data_addr(tex->id, &tex->depth, + &tex->size_line, &tex->endian); + if (tex->id == NULL) + return (FALSE); + } + return (TRUE); } diff --git a/src/texture.c b/src/texture.c index a5bf611..afeae92 100644 --- a/src/texture.c +++ b/src/texture.c @@ -6,7 +6,7 @@ /* By: cacharle +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/02/01 11:38:43 by cacharle #+# #+# */ -/* Updated: 2020/02/04 03:34:54 by cacharle ### ########.fr */ +/* Updated: 2020/02/04 23:16:02 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -45,7 +45,7 @@ t_image *texture_select(t_state *state, t_render_state *rstate) } else if (rstate->side == SIDE_WE) { - if (rstate->map_pos.x > state->pos.x) + if (rstate->map_pos.x < state->pos.x) return (state->textures + TEX_WEST); else return (state->textures + TEX_EAST); @@ -70,8 +70,8 @@ int texture_x(t_state *state, t_render_state *rstate, t_image *texture) wall_x = state->pos.x + rstate->perp_dist * rstate->ray.x; wall_x -= floor(wall_x); tex_x = (int)(wall_x * (double)texture->width); - if ((rstate->side == SIDE_NS && rstate->ray.x > 0) || - (rstate->side == SIDE_WE && rstate->ray.y < 0)) + if ((rstate->side == SIDE_NS && rstate->ray.y > 0) || + (rstate->side == SIDE_WE && rstate->ray.x < 0)) tex_x = texture->width - tex_x - 1; return (tex_x); } diff --git a/test.cub b/test.cub index 6324582..ffeda25 100644 --- a/test.cub +++ b/test.cub @@ -1,5 +1,16 @@ -11111 -10001 -10001 -10001 -11111 +R 1600 1200 +NO ./textures/eagle.xpm +SO ./textures/greystone.xpm +WE ./textures/wood.xpm +EA ./textures/greystone.xpm +S ./textures/cheese.xpm +F 10,10,10 +C 40,40,40 + +11 1 1 1 1 1 1 1 +10 0 0 1 0 0 0 1 +10 0 0 0 0 0 0 1 +10 0 0 N 0 0 0 1 +10 0 0 0 0 0 0 1 +10 0 0 0 0 0 0 1 +11 1 1 1 1 1 1 1 -- cgit