Hwan'Story › @kim-hwan

ShootGame 개발 중 문제해결 과정 정리

· (수정 ) · 조회 813

ShootGame 개발 중 문제해결 과정 정리

ShootGame은 웹으로 재미있는 무언가를 만들어보고 싶은 욕구로 만들게 된 간단한 멀티플레이 탑뷰 2D 슈팅게임입니다.

게임을 구현하기 위해 고민했던 부분을 정리하고자 글을 작성합니다.

image.png

시야 시스템

개요

게임의 처음 계획은 팀을 이뤄서 좀비를 잡는 컨셉으로 개발하려고 어두운 분위기를 만들기 위해 노력했다.

그러다 보니 보이지 않는 곳에서 갑자기 공격하는 적, 갑툭튀 등의 느낌을 2D에서 구현하기 위해서 시야 시스템을 고민하게 됩니다.

처음에는 RTS 게임 처럼 플레이어를 기준으로 동그란 원형 시야를 생각하게 되는데 이렇게 하니 사방에서 오는 적을 한눈에 파악이 가능해서 긴장감이 없었습니다.

그래서 플레이어가 보는 방향으로 부채꼴 모양의 시야를 만들어 플레이어의 후방은 보이지 않도록 구현하였습니다.

마지막으로 Reddit에서 여러 유저로부터 시야 시스템에 대한 칭찬이 많았는데 ShootGame 시야 시스템의 핵심인 시야내에 장애물이 존재한다면 장애물 뒤의 플레이어의 시야가 닿지 않는 부분은 보이지 않도록 하는 처리에 대해 어떻게 구현을 하였는지 순서대로 알아봅시다.

플레이어의 시야

우선 플레이어의 시야는 아래 그림과 같습니다. (부채꼴의 시야) image.png

장애물이 시야에 존재할 때 기대하는 시야 계산 결과물

플레이어의 시야 내에 장애물이 존재할 때 기대하는 시야 계산에 대한 결과물은 아래 그림과 같습니다.

장애물 너머의 영역은 시야 범위내에 있어도 장애물에 가려서 보이지 않아야 합니다.

(노란색 부분은 보이는 영역, 까만색 부분은 장애물에 가려 보이지 않는 영역)

image.png

결과적으로 원하는 시야에 대한 결과물은 다음과 같습니다.

image.png

image.png

결과적으로는 위 상황에서 원하는 건 11개의 꼭짓점을 가지는 다각형을 구해야 합니다. (Canvas의 drawPath 로 다각형을 그릴 수 있어 시야에 대한 효과 구현이 가능하다)

그러면 다각형을 그리기 위한 저 꼭짓점들은 어떻게 프로그래밍 하여 구할 수 있을까?

답은 플레이어의 중심점으로부터 무수하게 많은 선분을 그려 장애물과의 접점을 구하면 된다.

그러면 우선 무수하게 많은 선분을 구해야 한다. 선분은 다음과 같은 원리로 구할 수 있습니다.

image.png

각 Θ 를 조금씩 변화시켜 가며 무수하게 많은 선분을 구하면 됩니다. R의 값과 각 Θ 를 알고 있기 때문에 x와 y의 값을 구할 수 있다.

image.png

장애물은 사각형이므로 4개의 선분으로 표현이 가능하다. 따라서 장애물 1개당 4개의 선분이 나오게 되고, 위에서 구한 시야에 대한 선분과 접점을 구하면 됩니다.

문제점

위 방법의 문제점은 시야에 대한 무수하게 많은 선분을 구할 때 각 Θ의 변화량에 따라서 해상도가 달라진다는 점입니다.

Θ 값의 변화량을 작게 주면 줄수록 더 세밀하고 정확한 시야가 구해지게 되지만 구해야 할 선분과 접점 연산이 많아져 느려지게 됩니다. 그렇다고 Θ 값의 변화량을 크게 주면 해상도가 떨어져 정확하지 않은 시야가 구해질 확률이 높아지게 됩니다. 따라서 위 방법으로는 안되고 최대한 연산량을 줄일 수 있는 방법을 찾아야 했습니다.

해결책

시야에 영향을 주는 장애물의 부분은 꼭짓점입니다. 따라서 시야 내에 존재하는 장애물의 모든 꼭짓점을 기준으로 각 Θ를 구하면 연산량을 크게 줄일 수 있습니다. 꼭짓점을 기준으로 시야를 계산하면 다음과 같은 다각형을 구할 수 있습니다.

image.png

어? 뭔가 결과가 이상합니다. 꼭짓점이 11개인 다각형이 그려져야 하는데 7개인 다각형이 그려졌습니다.

이유는 장애물의 꼭짓점과 만나는 선분만을 그렸기 때문입니다. 따라서 광선이 꼭짓점 너머로 나아가지 못하여 그 뒤의 시야를 구하지 못한것입니다.

image.png

위 그림으로 보면 파란색 선분이 계산되지 않은 것입니다.

해결책

이 문제를 해결하려면 꼭짓점을 기준으로 Θ 값을 매우 미세하게 +- 하여 2 개의 선분을 더 추가하면 해결됩니다.

이렇게 하게 되면 장애물의 꼭짓점과 닿는 선분이 아닌 선분이 계산되기 때문에 장애물 너머의 선분 계산이 가능하게 됩니다.

결과물

Animation.gif

위 기능 구현에 대한 코드는 아래 파일에 작성되어 있습니다.

https://github.com/akon47/shoot_game/blob/master/lighting_class.js


파편 시스템

작성중 . . .