위아래시야의 조절하는 변수인 updown_sight도 단독으로 작동시키는 것 보다 key_release함수를 이용하는 편이 좀 더 동작이 매끄러웠습니다.
3️⃣ 동작 구현
(1) 좌, 우 동작구현
기존의 player의 위치를 업데이트해주는 함수인 update_player함수에 구현을 추가해 주었습니다.
doublemoveside=0.0;if(god->key.left==TRUE){walkDirection=1.0;moveside=PI/2.0;}if(god->key.right==TRUE){walkDirection=-1.0;moveside=HALF_PI;}/* 코드 생략 */newPlayerX=god->player.x+moveStep*cos(god->player.rotationAngle-moveside);newPlayerY=god->player.y+moveStep*sin(god->player.rotationAngle-moveside);if(!is_wall(newPlayerX,newPlayerY)){god->player.x=newPlayerX;god->player.y=newPlayerY;}return(0);
위의 코드를 보면 알듯이 현재위치에서 좌, 우로 이동하게 하려면 앞으로 이동할거리의 각도에 90도만큼의 각도변화를 주면됩니다.
HALF_PI라는 매크로로 90도를 표현했으며 walkDirection와 moveside의 부호는 방향에 맞춰서 잘 맞추면 됩니다. (90도의 각도변화를 준다는 것이 중요)
(2) 위, 아래시야 동작구현
구현하기 이전에 물리적인 관점에서 생각해 본다면 위 아래시야 각도에 따라서 모니터 위치에 따른 광선의 길이가 달라질 것입니다.
하지만 이전에 한 모니터상의 벽의 굴곡을 없애고 보정(어안렌즈효과 없앰)을 한 적이 있습니다.
이번문제점은 이번 포스트에서 구현한 내용때매 생긴 버그가 아닙니다. 단지, 좌, 우동작키를 구현하고 실험하는 과정에서 발견되었습니다.
방향각도의 수정없이(정확히 90도 유지) 한방향으로 벽에 부딪치면 시그멘트오류가 생기며 프로그램이 종료되었습니다.
그 이유는 distance(거리)의 값이 0이되는데 distance변수로 나눠주는 코드들이 많기 때문에 결국 무한대 값이 계산과정에서 어딘가에 생기게 됩니다.
이러한 버그는 기준각도가 정확히 90도의 배수일때만 발생하였는데, minilibx프로그램특성상 픽셀단위로 돌아가기 때문에 int값으로 보정되는 경우가 많습니다. 그렇기 때문에 다른 각도에서는 벽과 충돌하는 지점에서 distance(거리)의 값이 정확히 0이 나오는 경우는 거의 없었습니다.
(2) 문제해결
distance(거리)의 변수가 사용되는 곳의 함수에 조건문을 추가해주어 값을 보정해 주었습니다.
voiddraw_line(t_god*god,doubledx,doubledy){/* 코드 생략 */max_value=fmax(fabs(dx),fabs(dy));if(max_value==0)return;dx/=max_value;dy/=max_value;}
draw_line함수는 매개변수로 dx, dy(x, y좌표 각각의 거리)를 받아옵니다. 둘다 0이되어 max_value의 값이 0이 되는 것을 막아주었습니다.
if(god->ray.distance==0)god->ray.distance=0.1;
위의 코드는 3D벽을 그려주는 함수인 render_3D_project_walls함수에 추가해주었습니다.
5️⃣ 천장, 바닥색 커스텀함수 구현
천장, 바닥색을 커스텀해주는 함수의 구현은 간단합니다.
render_3D_project_walls함수에서 y축기준으로 wall_top_pixel부터 wall_bottom_pixel의 범위로 벽을 그려준다고 하였습니다.