[cub3d](12)파싱데이터 체크하기



1️⃣ 목표

  • 지금까지 (.cub)파일을 읽어서 구조체 변수에 저장하는 코드를 구현하였습니다.
  • 이제 구조체 변수에 필요한 데이터 값이 들어왔는지 체크하는 코드를 구현할 예정입니다.
  • 다음의 순서를 따를 것 입니다.
    1. 타입(xpm, color)가 값이 존재하는지 확인
    2. map(지도)에 올바른 값이 저장됨을 확인
    3. map의 요소(N, S, E, W에 따라 player위치 설정해주기
    4. 오류처리해주기


2️⃣ 타입(xpm, color)체크 함수 구현

(1) xpm파일 체크

int i;

i = -1;
while (++i < TEXTURE_COUNT)
    if ((god->parse.tex[i].tex_path) == NULL)
        return (ERROR);
  • 파일명이 반드시 .xpm일 필요가 없기 때문에 파일명에 대해서는 검사하지 않았습니다.
  • TEXTURE_COUNT헤더 부분에서 개발자가 사용할 텍스쳐파일의 갯수를 정확히 넣어줘야 합니다.

(2) color 체크

if ((god->parse.ceiling_color == NO_COLOR) || (god->parse.floor_color == NO_COLOR))
        return (ERROR);
  • ft_memset함수를 이용하여 모든 변수값을 0으로 초기화해주기 때문에 만약 “색깔을 설정하지 않았다면” color변수에 0이 저장되어 있을 것입니다.
  • 하지만 0값은 0x000000(검정색)을 나타내기도 합니다. 그렇다고 검정색을 설정하지 못하도록 할 수없는 노릇입니다.
  • 대신에 color변수는 -1로 초기화 해주었습니다. NO_COLOR(-1) 매크로로 정의해 주었습니다.

(3) 나머지 변수 체크

  • 위의 과정과 동일하게 나머지 변수들도 초기화된 값의 비교를 통해 체크할 수 있습니다.
  • 아직 보너스 파트를 구현하기 전이기 때문에 저같은 경우 다음의 변수들만 추가로 체크해줬으면 됐습니다.
if (!(god->parse.row) || !(god->parse.col))
    return (ERROR);




3️⃣ map(지도) 체크 및 player위치 설정

(1) 공백 요소

  • 기본 지도 요소0, 1, N, S, E, W공백입니다.
  • 공백은 말그대로 공백이며 0(복도)NSEW접촉해서는 안됩니다. (공백은 1(벽)으로 막혀있어야 한다)
/* 요소하나씩 탐색하는 wile문 내부 */
/* value = god->parse.map[row][col] */

if (ft_strchr("1 ", value) != NULL)
    continue;
else if (ft_strchr("0NSEW", value) != NULL)
{
    if (is_space_around_position(god, row, col) == ERROR)
        return (ERROR);
}
  • ft_strchr함수를 이용하여 체크를 하게 됩니다.
  • 요소가 0NSEW중 하나일 경우 is_space_around_position()함수를 호출하게 됩니다. 결과적으로 NSEW일 경우에는 방향을 체크하는 함수까지 필요하기 때문에 0일때 케이스와 분류하여 구현하였습니다.

(2) is_space_around_position()함수

int		is_space_around_position(t_god *god, int row, int col)
{
	if (row <= 0 || row >= god->parse.row || col <= 0 || col >= god->parse.col)
		return (ERROR);
	else if (god->parse.map[row][col + 1] == ' '
	|| god->parse.map[row][col + 1] == '\0' || god->parse.map[row][col - 1] == ' ')
		return (ERROR);
	else if ((int)ft_strlen(god->parse.map[row - 1]) <= col
	|| god->parse.map[row - 1][col] == ' ' || god->parse.map[row - 1][col] == '\0')
		return (ERROR);
	else if ((int)ft_strlen(god->parse.map[row + 1]) <= col
	|| god->parse.map[row + 1][col] == ' ' || god->parse.map[row + 1][col] == '\0')
		return (ERROR);
	return (SUCCESS);
}
  • 말그대로 공백이 있는지 확인해주는 함수입니다.
  • 현재 좌표에서 상, 하, 좌, 우의 값이 공백인지를 체크합니다.

(3) player위치 설정

  • 맵이 유효한지 체크가 끝났다면 NSEW(player가 바라보는 방향)값에 따른 player를 설정해 주면됩니다.
int     set_angle(t_god *god, int row, int col)
{
    char type;

    if (god->player.x != 0 || god->player.y != 0)
        return (ERROR);
    type = god->parse.map[row][col];
    if (type == 'E')
        god->player.rotationAngle = HALF_PI * 0;
    else if (type == 'S')
        god->player.rotationAngle = HALF_PI * 1;
    else if (type == 'W')
        god->player.rotationAngle = HALF_PI * 2;
    else if (type == 'N')
        god->player.rotationAngle = HALF_PI * 3;
    god->player.x = ((double)col + 0.5) * TILE_SIZE;
    god->player.y = ((double)row + 0.5) * TILE_SIZE;

    return (SUCCESS);
}
  • 이미 player의 좌표가 유효하다면 ERROR를 반환합니다.
  • N, E, S, W방향은 HALF_PI(90도)만큼씩 차이납니다. 적절하게 rotationAngle을 설정해줍니다.
  • player의 좌표는 좌표기준 정 중앙에 위치하도록 합니다. (TILE_SIZE를 이용)


4️⃣ 오류 출력(main함수)

  • 지금까지 구현한 코드들을 main함수에서 호출과 동시에 에러처리를 할 예정입니다.
  • 파싱에 대해서 오류가 나는 경우의수는 너무나 많습니다.
  • 그렇다고 각각의 오류 케이스마다 세부적으로 오류를 처리해주기에는 함수가 너무 복잡해질 것같고 나중에 코드를 수정할때도 만만치 않을 것이라고 생각이 들었습니다. (예를들어 집안에 누전차단기(두꺼비집)를 생각해보면 방단위로 처리하지 각각의 콘센트에 대해 처리하지 않습니다.)
    cub3d가 이전에 해왔던 과제들보다 복잡하기는 하나 감당이 가능한 정도이고 오히려 오류처리가 광범위하면 버그를 찾기가 더 힘들었습니다. 그래서 왠만하면 오류도 세부적으로 표시(출력)하도록 바꿨습니다.
int main(int argc, char **argv)
{
	t_god god;

	if (argc != 2)
		return (exit_error(&god, ERROR, "WRONG ARGUMENT COUNT!"));
	ft_init(&god);
	if (parse_file(&god, argv[1]) == ERROR)
		return (exit_error(&god, ERROR, "FAIL PARSING!"));
	if (check_parsing_value(&god) == ERROR)
		return (exit_error(&god, ERROR, "WRONG PARSING VALUE SAVED!"));
	render_player(&god);
    mlx_loop(god.mlx);
	return (0);
}
  • main함수에서는 크게 세가지 부분으로 오류를 출력하도록 하였습니다.




© 2021.02. by kirim

Powered by kkrim