[cub3d](14)제대로된 맵 파싱하기
1️⃣ 목표
get_next_line함수
를 이용하여 저장한 맵배열을보정 하여 새로운 변수에 저장할 예정입니다.- 굳이 새로운 변수를 만들어 옮기는 이유는 다음과 같습니다.
1. 미니맵을 그릴 때 최대 길이를 기준으로 항상 get_next_line함수
로 저장한 맵배열은 각각의 줄의 길이가 다를 수있습니다. 그럴경우
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 t
1 1 1 1 1
만약 쓰래기값이 우연히 1
과 같은 값으로 저장되어 있다면 벽
으로 인식하게 될 것입니다. 이러한 버그
가 일어나지않게 하기위함입니다.
2. 저장된 맵의 mlx함수
특성상
–>만약 저장된 맵의 row(줄),col(열)을 짝수가 되게끔 보정한다면
2️⃣ map 구조체 선언, 옮기기
(1) map 구조체 선언
typedef struct s_map
{
int map_rows;
int map_cols;
int window_width;
int window_height;
int ray_count;
char **map;
} t_map;
- 기존에 매크로로 정의했던
윈도우 너비
,윈도우 높이
,광선의 수
들은cub파일의 맵
에 따라 달라지게 되기 때문에 변수로 만들어map구조체
에 저장해 주었습니다.
(2) set_map함수
void set_map(t_god *god)
{
int y;
int row;
int col;
god->map.map = (char **)malloc(sizeof(char *) * god->map.map_rows);
y = -1;
while (++y < god->map.map_rows)
god->map.map[y] = (char *)malloc(sizeof(char) * (god->map.map_cols + 1));
row = -1;
while (++row < god->parse.row)
{
col = -1;
while (god->parse.map[row][++col] != '\0')
god->map.map[row][col] = god->parse.map[row][col];
col--;
while (++col < god->map.map_cols)
god->map.map[row][col] = ' ';
god->map.map[row][col] = '\0';
}
free_array_memory((void **)god->parse.map, god->parse.row);
}
- 기존에
parse->map
변수에ft_split함수
를 이용하여 요소를 저장했었습니다. 이것을 최대 열길이에 맞춰서2차원 동적할당 을 해주었습니다. - 그후 조건문을 통해 뒤쪽의 쓰래기값 대신
공백
이 저장해 주었습니다.
3️⃣ 모서리가 통과되는 버그
(1) 버그 발견
- 벽의 구조가 다음과 같을 때
광선(ray) 가 통과하는 현상이 발견되었습니다. 당연히 player 도 통과가 되었습니다.
0 1
1 0
- 어짜피
player
의 부피를 서브젝트가 정의해주지 않았기때문에 모서리를 통과해도 괜찮지 않을까 생각을 했지만 그래도통과하지 못하도록 막는 것 이 상식적으로 맞을 것 같습니다. - 먼저 문제의 원인은 제가 구현한 렌더링함수는
픽셀단위로 모든 벽을 탐색하지 않습니다. - 우연히 꼭지점을 탐색하더라도
꼭지점 기준 왼쪽 상단 의 좌표로 인식할 것입니다.
(2) 버그 해결하기
- 벽을 탐색하는 함수인
is_wall()
함수를 수정해줄 필요가 있습니다.
int check_edge(t_god *god, double x1, double x2, double y1, double y2)
{
int dx;
int dy;
dx = (int)(x1 / TILE_SIZE) - (int)(x2 / TILE_SIZE);
dy = (int)(y1 / TILE_SIZE) - (int)(y2 / TILE_SIZE);
int dx2 = (int)(x1 / TILE_SIZE);
int dy2 = (int)(y1 / TILE_SIZE);
if (dx == 1 && dy == 1)
return (ft_strchr("0NSEW", god->map.map[dy2 - dy][dx2]) == NULL) && (ft_strchr("0NSEW", god->map.map[dy2][dx2 - dx]) == NULL);
if (dx == 1 && dy == -1)
return (ft_strchr("0NSEW", god->map.map[dy2 - dy][dx2]) == NULL) && (ft_strchr("0NSEW", god->map.map[dy2][dx2 - dx]) == NULL);
if (dx == -1 && dy == 1)
return (ft_strchr("0NSEW", god->map.map[dy2 - dy][dx2]) == NULL) && (ft_strchr("0NSEW", god->map.map[dy2][dx2 - dx]) == NULL);
if (dx == -1 && dy == -1)
return (ft_strchr("0NSEW", god->map.map[dy2 - dy][dx2]) == NULL) && (ft_strchr("0NSEW", god->map.map[dy2][dx2 - dx]) == NULL);
return FALSE;
}
check_dege()
함수를 이용하여is_wall()
함수로 벽을 확인할때 이 함수를 추가로 사용하여 검사해주도록 하였습니다.이제
광선(ray)
과player
모두 통과하지 않습니다.