참고한 링크
map.cub로 부터 map을 불러온 후, 모든 유효성 검사가 완료되면 저장된 map의 정보를 바탕으로 lodev 튜토리얼에 따라 floor, ceiling, wall을 만들고 player의 초기 위치, 키 값에 따른 회전과 움직임을 설정한다.
lodev tutorial - wall
0
: 비어있는 공간
1
: 벽
N
,S
,W
,E
: player (초기 설정 방향)
그 외 : error
typedef struct s_player
{
double pos_x;
double pos_y;
double dir_x;
double dir_y;
double plane_x;
double plane_y;
t_move_hor_ver movement; // 이동 설정
t_move_hor_ver rotation; // 회전 설정
} t_player;
t_player *player;
player->pos_x, player->pos_y
: 플레이어의 초기 위치벡터
player->dir_x, player->dir_y
: 플레이어의 초기 방향벡터
player->plane_x, player->plane_y
: 플레이어의 카메라 평면
- 카메라 평면은 방향벡터와 수직이기만 하면 변수선언시 길이가 다양할 수 있다.
- 이 코드에서는 카메라 평면보다 방향벡터가 약간 더 길어서 FOV가 90°보다 작다.
(정확히는 FOV = 2 * atan(0.66/1.0)=66.8°로 1인칭 슈팅게임(fps)에 적합)
- 초기선언 이후에는 입력키로 회전해서 방향벡터 dir과 카메라 평면 plane의 값이 변경되더라도 항상 서로 수직이어야 하고 동일한 길이가 유지되어야 한다.
typedef struct s_wall_info
{
double camera_x;
double raydir_x;
double raydir_y;
double side_dist_x;
double side_dist_y;
double delta_dist_x;
double delta_dist_y;
double perp_wall_dist;
double wall_x;
double step;
double tex_pos;
int map_x;
int map_y;
int step_x;
int step_y;
int hit;
int side;
int line_height;
int draw_start;
int draw_end;
int tex_num;
int tex_x;
int tex_y;
int color;
int x;
int y;
} t_wall_info;
t_wall_info *wall;
wall->camera_x
: x값(화면의 수직선)의 위치가 카메라 평면에서 차지하는 x좌표
(반복문에서 x값이 0[스크린의 왼쪽 끝]이면 wall->camera_x = -1,
x값이 width/2[스크린의 중앙]이면 wall->camera_x = 0,
x값이 width[스크린의 오른쪽 끝]이면 wall->camera_x = 1)
이를 이용해서 광선의 방향을 계산한다.
wall->raydir_x, wall->raydir_y
: 광선의 방향벡터
광선의 방향은 (플레이어의 방향벡터) + (카메라 평면 * 배수)이다.
벡터 x, y에 대해 각각 이 계산을 해준다.
wall->map_x, wall->map_y
: 현재 광선의 위치, 광선이 있는 한 칸 (정확한 위치가 아닌 존재하고 있는 그 한칸의 좌표)
t_wall_info *wall;
wall->side_dist_x, wall->side_dist_y
: '시작점 ~ 첫번째 x, y면을 만나는 점'까지의 광선의 이동거리 (나중에 의미가 약간 변경된다)
wall->delta_dist_x, wall->delta_dist_y
: '첫번째 x, y면 ~ 바로 다음 x, y면'까지의 광선의 이동거리
wall->perp_wall_dist
: 벽에 부딪힐 때까지의 광선의 이동거리를 계산하는 수직광선의 길이
wall->step_x, wall->step_y
: DDA 알고리즘은 반복문을 실행할 때마다 x 또는 y 방향으로 한 칸씩 점프하는데
광선의 방향에 따라 어느 방향으로 건너뛰는지를 +1, -1로 저장
wall->hit
: 벽과 부딪혔는지 여부 (루프 종료조건)
wall->side
: 벽과 부딪혔을 때, x면에 부딪혔으면 0이고 y면에 부딪혔으면 1.
t_wall_info *wall;
wall->camera_x = 2 * wall->x / (double)WIDTH - 1;
wall->raydir_x = player->dir_x + player->plane_x * wall->camera_x;
wall->raydir_y = player->dir_y + player->plane_y * wall->camera_x;
wall->map_x = (int)player->pos_x;
wall->map_y = (int)player->pos_y;
wall->delta_dist_x = fabs(1 / wall->raydir_x);
wall->delta_dist_y = fabs(1 / wall->raydir_y);
wall->hit = 0;
if (wall->raydir_x < 0)
{
wall->step_x = -1;
wall->side_dist_x = (player->pos_x - wall->map_x) * wall->delta_dist_x;
}
else
{
wall->step_x = 1;
wall->side_dist_x = (wall->map_x + 1.0 - player->pos_x) * wall->delta_dist_x;
}
if (wall->raydir_y < 0)
{
wall->step_y = -1;
wall->side_dist_y = (player->pos_y - wall->map_y) * wall->delta_dist_y;
}
else
{
wall->step_y = 1;
wall->side_dist_y = (wall->map_y + 1.0 - player->pos_y) * wall->delta_dist_y;
}
1) wall->step_x, wall->step_y
광선의 x방향(raydir_x) > 0, step_x : +1,
광선의 y방향(raydir_y) > 0, step_y : +1,
광선의 x방향(raydir_x) < 0, step_x : -1,
광선의 y방향(raydir_y) < 0, step_y : -1
광선의 방향(raydir_x, raydir_y) == 0, step은 사용되지 않으므로 어떤 값을 갖든 상관없다.
2) wall->side_dist_x, wall->side_dist_y
광선의 x방향(raydir_x) > 0,
side_dist_x : 광선의 시작점부터 오른쪽으로 이동하다 처음 만나는 x면까지의 거리
광선의 x방향(raydir_x) < 0,
side_dist_x : 광선의 시작점부터 왼쪽으로 이동하다 처음 만나는 x면까지의 거리
광선의 y방향(raydir_y) > 0,
side_dist_y : 광선의 시작점부터 위쪽으로 이동하다 처음 만나는 y면까지의 거리
광선의 y방향(raydir_y) < 0,
side_dist_y : 광선의 시작점부터 아래쪽으로 이동하다 처음 만나는 y면까지의 거리
초기화 (x, y동일)
wall->raydir_x > 0,
wall->side_dist_x = (wall->map_x + 1.0 - player->pos_x) * wall->delta_dist_x;
광선의 위치 실제 위치
wall->raydir_x < 0,
wall->side_dist_x = (wall->pos_x - wall->map_x) * wall->delta_dist_x;
실제 위치 광선의 위치
초기화 (x, y동일)
wall->raydir_x > 0,
wall->side_dist_x = (wall->map_x + 1.0 - player->pos_x) wall->delta_dist_x;
광선의 위치 실제 위치
wall->raydir_x < 0,
wall->side_dist_x = (wall->pos_x - wall->map_x) wall->delta_dist_x;
실제 위치 광선의 위치
여기서 실제위치랑 광선의 위치 개념이 이해가 잘 안되는데 혹시 도와주실수있으실까요?