2학년 1학기 게임프로그래밍 과제로 제출한 유니티 2D 게임이다.
게임 제목, 개요, 기획의도
게임 제목: Space
우주라는 뜻과 오로지 스페이스 키만을 눌러서 진행한다는 중의적인 의미를 가지고 있다.
게임 개요:
2D 게임으로 다음과 같습니다.
게임을 시작하면, 플레이어는 행성을 중력권 범위에 맞게 빙빙 돈다.
2. 스페이스키를 누르면 현재 움직이고 있던 행성이 터지며 중력이 사라지고 원래 이동하던 방향대로 쭉 이동한다. 그리고 새로운 행성이 랜덤으로 생성된다.
3. 맵 밖으로 나가면 게임 오버 되므로, 스페이스를 눌러 행성을 떠날 때는 항상 다른 행성을 찾아서 움직이는 방향으로 가야 한다..
4. 그렇게 새로운 행성의 중력권 안에 들어갈 때마다 점수가 +1 된다.
기획 의도
유저가 직관적으로 이해할 수 있는 간단한 게임을 만들고 싶었다. 긴 설명이 필요한 게임은 그 자체로 진입장벽이 된다. 게임의 규칙을 글로 풀어내는 데는 몇 줄이 걸리더라도 사용자의 직관은 그보다 더 쉽게 바로 이해할 수 있도록 만들고 싶었다. 위의 과정은 설명없이 직관적으로 스페이스를 누르기만 하다 보면 깨닫게 된다. 그래서 스페이스 키만 눌러도 될 정도로 간단하지만, 게임 자체가 쉽진 않으며, 랜덤적 요소가 있어 매판 할 때마다 달라지는 재미를 느끼게 하고자 이 게임을 만들었다.
행성 랜덤 생성 방식
게임의 재반복성을 위해 게임을 처음 시작할 때마다 랜덤으로 행성들이 생성된다. 그런데 여기서 2가지 문제가 발생하였다.
1.행성끼리 겹치면 안 된다,, 즉 랜덤으로 생성하되, 다른 행성의 원형의 중력권 범위와 겹쳐서는 안 된다.. 행성끼리 겹쳐진 모습은 플레이어의 몰입을 깨뜨린다. 생성할 때 어떻게 해야 서로 겹치지 않게 할 수 있을지 고민이 많았다.
2. 초기 맵 생성 이후에도 유저가 행성을 떠나면 그 행성이 사라지고, 새로운 행성이 생성된다. 그때도 새로운 행성이 겹쳐서는 안 된다..
2가지 문제들을 해결하기 위해 우선 같이 전체 맵의 범위를 나누었다.
맵을 크기에 따라 5*5 범위로 나누고, 저 범위마다 다음과 같이 숫자를 부여했다.
20 | 21 | 22 | 23 | 24 |
15 | 16 | 17 | 18 | 19 |
10 | 11 | 12 | 13 | 14 |
5 | 6 | 7 | 8 | 9 |
0 | 1 | 2 | 3 | 4 |
그리고 행성 개수만큼 0~24 중에서 뽑고, 해당하는 번호에만 생성한다.
가령 행성개수를 6개로 설정해 놓았다면 3,9,16,17,20,24 3,9,16,17,20,24라는 번호가 뽑히고 그러면 해당하는 위치번호 안에서 행성이 랜덤으로 생성된다. 이때 위치가 경직되어 있다는 느낌을 주면 안 되므로 저 구역 안에서도 랜덤 한 위치에서 생성되게 하였다.
가령 사진의 경우 1, 3, 4, 7, 12, 16, 20, 22, 23, 24 위치에 생성된 것이다.
단, 게임 시작할 때 유저는 맵의 한 가운데에서 시작되어야 하므로, 처음에 12번 위치에는 행성이 무조건 (0,0) 의 좌표로 생성되게 하였다.
게임 중간에 새로운 행성이 생성될 때도 현재 맵에서 어디에 행성이 생성되었는지 확인하고 생성되지 않은 구역의 번호 중에서 랜덤으로 하나를 골라 생성되게 하였다.
원래 공전하던 행성이 떠나면 사라지는 이유
만약 원래 공전하던 행성이 사라지지 않으면, 이론상 유저가 똑같은 행성 2개만 왔다갔다 하면서 계속 점수를 늘릴 수 있다. 이는 게임성을 떨어뜨린다. 따라서 유저가 행성을 떠나면 그 행성은 사라진다. 그리고 다른 행성이 랜덤으로 생성된다.
생성되는 행성의 랜덤성
게임의 리플레이성을 위해서 행성은 위치, 색깔, 방향, 모양, 크기 모두 랜덤이다.
위치는 위에서 설명한 대로 구역을 나누어 구현했다.
방향과 색깔은 transform.rotation.z와 Color의 RGB를 랜덤으로 하는 방식으로 구현하였다.
행성의 모양은 sprite render의 이미지를 이름을 랜덤으로 가져와서 랜더링 하는 식으로 하였다. 이때 렌더링 되는 행성이미지의 크기나 색깔이 코드의 색깔, 크기 랜덤생성에 영향을 미치지 않게 하기 위해 모두 무채색으로 만들고, 모두 같은 크기로 편집했다.
safeline의 개념
하지만 행성의 크기는 랜덤으로 처리할 때 색깔, 방향 등과는 다르게 처리해야 한다. 행성이 너무 크면 구역을 나누었어도 이웃한 구역끼리 서로 운이 없게 겹칠 수도 있기 때문이다. 가령 행성 하나는 1번위치의 가장 오른쪽에 생성되었고,, 다른 하나는 2번에서 생성되었는데 가장 왼쪽에 생성되었으면 행성 2개가 서로 경계선을 넘어 겹칠 수도 있다. 그래서 safeline이라는 변수 값이 등장한다. 이 말인 즉슨 .저 범위 안에서도 경계선으로 접근하는 안전거리가 필요한 것이다. 그래서 행성의 최대반지름 길이를 safeline으로 만들어 주었다. 이는, 서로 행성 둘이 인접하는 최악의 경우가 발생하더라도 결코 겹치지는 않는다. 즉, 25개로 나눈 표의 저 범위 안에서도 안전거리만큼의 상하좌우 생성위치를 줄여 제한하였다. 따라서 생성 위치는 다음과 같이 된다.
맵을 다음과 같이 표시할 수 있다. 초록색 범위가 행성끼리 겹치지 않게 하기 위해 행성이 생성되지 않는 safeline 범위이다. 파란색 범위 안에서 랜덤으로 행성들이 생성된다.
행성과 그 중력권
행성은 생성될 때마다 그 행성과 그 행성의 중력권 2개가 생성된다. 행성만 있거나 중력권만 있으면 우주를 다루는 게임의 콘셉트를 떨어뜨릴 것 같아 일부러 2개 만들었다. 실질적으로 유저가 도는 콜라이더도 그 행성이 아닌 그 행성의 중력권을 인식하고 충돌 판정해 돈다. 행성의 중력권 역시 행성의 색깔과 크기에 비례해서 생성된다.
안에 있는 것이 행성, 그 밖에 있는 것이 플레이어와 충돌 판정을 해서 공전을 하게 하는 중력권이다.
시계방향과 반시계 방향
유저가 새로운 행성에 도착하면 이제 직선운동이 아닌 중력권을 따라 원으로 돌게 된다. 이때 원운동도 2가지 선택지가 있다. 시계방향으로 돌지 반시계방향으로 돌지다. 유저가 게임을 직관적으로 이해하려면, 이 2가지 방향도 원래 직선운동과 더 비슷한 방향이어야 한다. 따라서 행성의 중력권과 충돌할 때 기존 직선 방향이 현재 행성의 2가지 접선 각도 중 어디에 더 가까운지 판단하여 시계방향과 반시계방향 중 어디로 가는지 계산한다.
카메라 무빙
카메라는 행성을 항상 따라간다. 카메라는 행성이 중력권 안에서 움직일때는 다른 행성을 플레이어가 찾고 이동을 미리 계획할 수 있도록 점점 화면이 줌 아웃된다.카메라가 비추는 범위가 넓어지며 플레이어는 다음으로 이동할 행성의 위치를 미리 계획하고 탐색할 수 있는 단계를 가지는 것이다.
최대로 줌 아웃된 모습이다.
반대로, 스페이스를 눌러 직선으로 이동하는 동안에는 플레이어가 더 이상 할 수 있는 게 없다. 그래서 이동하는 동안 시야를 축소시켜 행성에 안착할 수 있을지 약간의 불안감을 준다. 이는 중력권 안에서 공전하느라 뒤로 간 카메라를 다시 앞으로 당겨주는 역할도 한다.
플레이어가 직선으로 이동하느라 줌인된 모습이다. 줌아웃 되었을 때와 범위의 차이가 확실히 느껴진다.
레벨디자인
그러면 플레이어가 그냥 무한정 시야가 확대될 때까지 기다렸다가 스페이스를 누를 수도 있다. 이렇게 무한정 기다리는 방식은 게임의 긴장감을 떨어뜨리고 지루하게 만든다. 따라서 두 가지 방식을 도입했다.
카메라 축소/확대의 제한 범위 : 아무리 공전해도 일정 수준 이상으로는 카메라가 줌아웃 되지 않는다.
공전하는 동안 속도가 가속:
레벨디자인 적인 요소로 행성에 안착한 후에는 Time.time이 작동해 중력권을 돌면서 머무른 시간에 비례해 속도가 점점 빨라진다. 물론, 일정 수준이상은 빨라지지 않고, 다른 행성에 안착하면 이 가속은 사라진다. 하지만 점점 빠르게 만듦으로써 오랫동안 기다리면 그만큼 타이밍 잡기가 어렵게 만든다. 즉 유저는 시야확보와 완벽함을 위해 기다려야 한다고 판단할 수도, 속도가 빨라질수록 컨트롤하기 어려워지므로 빨리 눌러야 한다고 판단할 수도 있다. 유저는 이 딜레마 사이에서 중간점을 찾아간다. 또한 이렇게 증가한 속도는 몰입감을 위해 행성을 떠나고 다른 행성으로 안착할 때 직선으로 나아갈 때도 유지되게 하였다.
Indicator
그런데 정말로 주변에 행성이 잘 안보일 수도 있다. 운이 없게도 유저가 간 위치는 행성이 거의 없는 위치였을 수 있다. 그런 운 적인 요소를 보완하기 위해 indicator를 제공한다. indicator는 현재 카메라에는 보이지 않지만, 가장 가까이 있는 행성의 중심 방향을 흐리게 보여준다. viewport와 lineRender를 사용하였다.
행성의 위쪽으로는 노란 행성을 지나온 행성의 궤적이, 아래쪽으로는 indicator가 현재 화면에는 보이지 않는 가장 가까운 행성의 방향을 알려준다. 화면에 보이는 2가지 행성은 가까이 있지만, 화면을 기준으로 행성의 중심이 보이기에 indicator는 유저가 이미 알고 있을 거라 여기고 그다음으로 가까운 행성을 가리킨다..
이는 현재 맵에 보이지 않더라도 다른 행성의 대략적인 위치를 알 수 있다. 또한, 매순 간 반영되기에 행성의 방향뿐만 아니라 행성의 위치도 계산이 가능하다. 이런 요소는 게임이 단순히 운에만 의존하지 않도록 한다.
색감
유저는 움직이면서 궤적을 trailRenderer로 남긴다. 또한 궤적의 색깔은 현재 공전하고 있는 그 행성의 색깔이다. 정확히는, 궤적이 너무 진하면 시각적으로 방해되기에 해당 색깔을 옅하게 한 색깔이다. 따라서 새로운 행성의 공전권 안에 들어올 때마다 색깔이 달라진다. 유저는 자신이 이동한 발자취를 시각적으로 느낄 수 있음과 동시에 색깔이 현재 공전하고 있는 행성으로 바뀌어서 색채적 동일성을 느낄 수 있다.
indicator가 보여주는 궤적 역시 현재의 유저의 궤적 색깔로 시작해 indicator가 가리키는 행성의 색으로 끝이 난다.이는 색채적인 통일성을 트레일 렌더러와 같은 원리를 적용해 게임의 일관성을 유지하였다.
또한 indicator의 투명도가 현재 플레이어의 위치는 0이고 행성에 갈수록 진해지므로, 농도를 보고 얼마나 멀리 떨어져 있는지 추정할 수 있다.
희미하게 위쪽에 indicator가 가장 가까운 행성을 가리키는 걸 볼 수 있다. 또한 유저가 남기는 궤적과 행성, 행성의 중력권 색깔이 통일감을 준다.
그 외 완성도를 위해 다듬은 것들
청각적 피드백
효과음으로 행성에 안착하면 좋은 소리가, 게임오버면 안 좋은 소리가 나게 했다. 이 소리들은 바구니 폭탄 게임 만들 때 썼던 리소스들이다.
레이어 순서
레이어 순서를 행성> 중력범위 >라인렌더러, 트레일 렌더러 > 배경 순으로 두었다. 그래서 생기는 궤적들이 행성 위로 가서 몰입감을 떨어뜨리는 것을 차단했다.
제네레이터
배경 크기와 생성되는 행성 개수는 모두 Generator의 변수 하나에 맞게 자동으로 되게 통합시켰다. 그래서 맵 크기나 초기 행성의 수로 밸런스를 조절할 때 변수 하나만 바꾸면 되게 편하게 리팩토링 하였다. 거의 모든 정보가 Generator에 저장되고, 거기서 받아오기에, 이후에도 수정하기 매우 용이하다.
게임오버 조건
일부러 선을 넘어도 유저가 완전히 넘어갔다고 인식하는 시간적 여유가 필요할 것 같아서 넘어간 지 조금 지나서 게임오버를 시켰다.
행성을 공전하는 상태가 아닌데 맵의 범위를 벗어나면 더 이상 만날 공전할 행성이 없으므로 게임오버된다. 게임 오버되면 다음과 같이 효과음이 나고, 플레이어가 축소되면서 끝난다.
점수의 가시성
점수의 가시성을 위해 점수 뒤쪽에 반투명 검은 패널을 두었다.
webGL로 배포
편하게 게임할 수 있도록, webGL로 배포하였다.
배포 링크: https://play.unity.com/mg/other/webgl-builds-422008
결론
리소스 출처
소리: 겜프 수업에서 활용한 바구니로 폭탄을 받을 때 난 소리, 바구니로 사과를 받을 때 난 소리 2가지를 사용했다.
이미지: 인터넷에서 무료 행성 이미지를 다운로드하여 크기와 채도를 변경했다. 배경이미지는 ai한테 생성시킨 후 내가 편집했다.
게임 아이디어: 원래는 순수 내 창작이었다. 그런데 스윙바이라는 비슷한 게임이 있다는 것을 뒤늦게 알게 되었다.. 게임을 다 만들고야 알아서 코드나 어셋 부분은 전혀 기존 스윙바이를 참고하지 않았다.
예전부터 간단하면서 직관적인 게임을 하나 만들고 싶었다. 이전에 감당 못할 크기로 유니티 프로젝트를 만들었다가 망했던 경험 때문에 더 그랬던 것 같다. 중력에 이끌리고 나아가는 힘은 가장 직관적으로 잘 이해된다고 생각해 이런 프로젝트를 만들었다. 작은 규모임에도 디테일을 다듬는 데는 오랜 시간이 걸렸다. 기존 기획과 세부 사항이 달라지기도 했다. 원래 indicator는 느낌표 모양의 UI로 화면 끝에 표시하려 했으나 변경되었고, 원래는 우주배경이 아닌 종이 위에서 펜을 긋는 콘셉트이었다. 무엇을 표현하고 싶은가? 에 맞추어 기획을 더 유저가 받아들일 수 있도록 계속 수정해 나갔다.
'개발' 카테고리의 다른 글
[멋쟁이 사자처럼] 12기 해커톤 후기! (2) | 2024.08.14 |
---|---|
[리눅스 프로그래밍] WSL환경에서 Kernel 컴파일 하기 (1) | 2024.06.30 |
[웹 프로그래밍] 나만의 사이트 만들기 (0) | 2024.06.30 |