안녕하세요!
이런저런 게임을 구현해보기 위해 여러가지 연습해보고 있습니다.
만들어 볼 게임은 " 퍼즐 버블 " 스타일의 게임입니다.
여러가지 로직이 생각나는데, 가장 중요한 핵심 로직들은 생각해보니 복잡하지 않았고, 몇가지 이론들만 알면 금방 뚝딱 만들어 낼 것 같아요.
이와 비슷한 게임은 많은 것 같은데, 가장 대표적인건 역시 퍼즐 보블인 것 같습니다.
장르 : 퍼즐, 전략, 슈팅
소요 시간 : 약 31시간
1일차 8시간
2일차 12시간
3일차 11시간
핵심 로직
마우스,터치 포인터 각도로 발사
벽에 튕긴 후 궤적을 표현 ( 게임엔 1번 까지만 표현 )
구슬을 6각으로 구분하여 충돌 포인트 계산 ( 클론 생성 )
인접 구슬 파괴 로직 구현
위에 연결된 구슬이 없을 경우, 이하 아래 모든 구슬 파괴로직 구현 ( 중력 )
이 정도 5가지만 구현하면 될 것 같습니다.
1,2,3번은 금방 구할것 같고, 4번 로직이 BFS & DFS, 그래프 이론 등으로 구할 수 있을 것 같네요.
5번은, 블럭단위로 섹션을 나눠서 구할 수 있는지 한번 체크해 봐야 할 것 같아요.
이번 아티클 에서는 1,2,3 까지 해볼 것 같습니다.
마우스, 터치 포인터 각도로 발사
마우스 클릭 지점을 기준 방향으로 구슬을 보내기 전 플로우를 설정했습니다.
1. 마우스 클릭 지점 중, 시작, 도착 지점을 자료구조로 가지고 있는다.
2. 방향벡터를 구해서 발사 한다.
여기서 2가지로 구현 방식이 나뉜다고 생각합니다.
1. 구슬을 발사하여 충돌 시, Y 기준으로 반전하여 이동할 수 있게 버블에 기능을 준다.
2. 구슬이 이동할 라인을 모두 생성하고, 구슬을 정해진 라인으로 이동할 수 있게 한다.
여기서 저는 버블은 단순히 날아가는 역할만 했으면 좋겠다고 생각해서, 2번으로 구현할 예정입니다.
그렇기 위해, IPointerDownHandler, IDragHandler,IPointerUpHandler 을 터치 패널에 모두 사용해서 구현할 것입니다.
IPointerDownHandler : 입력의 시작점, 이때부터 라인은 계산
IDragHandler: 이미 입력은 되어 있지만 조금이라도 이동 시, 라인 갱신
IPointerUpHandler : 버블을 발사하는 입력, 터치 패널 클릭 ( 마우스 클릭 ) 을 떼면 호출됩니다.
화면을 터치한 좌표를 월드행렬로 변환하여 Ray를 발사해서 TouchArea 에 맞은 지점을 계산 한 후,
버블의 시작점과 맞은 지점의 방향 벡터를 구해서 그 방향으로 발사해줍니다.
벽에 튕긴 후 궤적을 표현
벽에 튕긴 후 궤적을 표현하는 부분은 직선의 방정식으로 구할 수 있는데, ( Y = AX + B )
사각형의 모든 직선의 방정식을 구하고, 설정한 방향 벡터로 나아가는 벡터의 직선의 방정식을 구합니다.
방향벡터 d = (dx,dy) 로 가정 (x,y) = (x0 + t*dx, y0 + t*dy) 로 설정합니다.
t는 매개변수, t값이 증가할 수록 점이 벡터를 따라 변경.
방향 벡터에 따른 직선의 방정식을 변의 직선 방정식으로 대입, t 산출
t 를 이용해 x,y 계산. 교점 좌표를 구합니다.
각 교점 좌표들이 사각형 위에 존재하는지, 끝점들 사이에 존재하는지 확인한 후 , t > 0 인 좌표를 구한 후, 가장 작은 t 값을 가지는 교점을 선택, 이 값이 가장 마지막까지 사각형 위에 있는 점
( 즉, 외부로 나가는 첫번째 좌표 ) 입니다.
구슬을 6각으로 구분하여 충돌 포인트 계산 ( 클론 생성 )
보통 이런 퍼즐 버블 스타일의 게임에선 구슬의 예상 도착 지점을 찍어줍니다.
그것을 구현하기 위해서는 대략적인 삼각함수 개념이 필요한데, 크게 어렵지는 않고, 저는 초기에 아래 그림처럼 생각해서 구현했습니다.
좌측, 우측에 방향레이가 도달했을때는 각각 좌,우 만큼 띄운 뒤 클론 생성,
좌하, 우하 일때는 좌측 아래, 오른쪽 아래에 생성합니다.
Right 벡터를 기준으로
-315 ~ 45 우측
45 ~ 135 위( 필터, 필요 X )
135 ~ 225 (좌측)
225 ~ 270 (좌하)
270 ~ 315 (우하)
로 각도를 설정했습니다.
구하는 방법은 아래와 같습니다.
1. 발사대의 좌표와, 레이를 맞은 지점의 좌표의 방향 벡터를 구하고, 버블의 회전은 변경되지 않는다는 가정하에, Right 벡터를 기준으로 잡고 내적합니다.
2. 내적의 공식은 a · b = |a||b| Cosθ 입니다.
|a||b|를 넘겨주면 아래와 같은 공식이 나옵니다.
Cosθ = a · b / |a||b|, 여기에서 각도를 구하기 위해, ArcCosθ(cosTheta) 값을 넣으면 각도를 받습니다.
3. ArcCos의 값 표현 범위는 0 ~ 180 도 이기 때문에, 전체 360를 표현하기엔 무리가 있습니다. 그렇기 때문에, 외적을 사용하여, 플레이어 기준 좌우측을 판단하는 것 처럼 Vector3.Cross(Right,dir) 로 새롭게 생성되는 벡터가 Y 양수일지, Y 음수일지 체크하여 360 - Degree 를 할지 Degree를 볼지 결정하여 정확한 각도를 받을 수 있습니다.
4. 그렇게 각도를 결정하면 미리 지정해둔 크기와 위치좌표를 연산하여 클론의 자리를 잡아줍니다.
나머지는 아티클 2부에서 작성하겠습니다.
1부 개념만 사용하는데에도 생각한것보단 상당수 수학적 개념이 들어가네요.
2부 개념은 수학적 개념보단
인접 구슬 파괴 로직 구현,
위에 연결된 구슬이 없을 경우, 이하 아래 모든 구슬 파괴로직 구현 ( 중력 )
을 구현하기 때문에, 알고리즘적 요소를 많이 설명할 것 같습니다.