본문 바로가기
모작 & 창작

[창작] DirectX11 3D 1주일 팀 프로젝트 "2인용 리듬+수영 게임"

by MY블로그 2023. 6. 7.

3D 수업이 시작되고 약 한달이 경과하였습니다.

이 시점에 그간 배워온 내용으로 작게나마 프로젝트를 진행해 보는 기간이 있었습니다.

기간은 짧게 1주일로 정하여 3명의 팀원끼리 간단한 게임을 만들게 되었습니다.

일주일 간의 프로젝트 기간을 마치고 정리를 해보려 합니다.

 

DAY 0.

우선 프로젝트 시작 전날은 3명의 팀원이 최우선적으로 어떠한 게임을 만들까 의견을 내는 날 이었습니다.

3D를 배우며 아직까지 지식이 충분하지 않기 때문에 만들어보고 싶은 게임은 장대하였으나....한정적인 기술만을 가지고 게임을 정해야했고 그로인하여 복잡한 로직이나 화려한 이펙트를 넣을 수 없었기에 아쉽지만 아주 심플한 게임 위주로 주제를 정하기로 했습니다.

 

우선 제일 먼저 제안된 게임은 볼링 게임 이었습니다.

간단히 구체 형태의 객체를 만들고 회전운동을 주어 멀리 있는 볼링핀을 쓰러뜨립니다.

하지만 너무 단순하고 재미가 없을 듯 하였기때문에 단순하게 각도와 힘을 정해 볼링 공만을 굴리는 것이아닌 박자를 맞출 수 있도록 리듬게임 방식이 제안되었습니다.

 

하지만 볼링 + 리듬 ? 으로 과연 재미있을까.. 하는 생각이 우선적으로 떠올라 다른 방안도 생각해 보게 되었습니다. (일반 볼링의 룰을 적용시켜 2명이 게임을 하더라도 게임의 턴이 너무길고 단순한 반복 게임이기때문에 루즈해질 것 같았습니다 때문에 첫번째 재안 CUT)

 

그다음으로 제안 된 것은 2인용 게임 + 리듬 게임 이라는 방식으로 주제를 맞추었고

거기서 플레이어의 다양한 모션을 보여줄 수 있을 듯한 수영 게임은 어떨까하며 주제가 정해졌습니다.

 

팀원중 로아(로스트아크)를 하는 팀원이 2명이나 있었기때문에 리듬게임 방식에 '아재패턴'을 적용하는 것이 좋겠다는 의견이 나왔고 바로 채용 되었습니다.

(아재패턴 : 정해진 시간내에 제시된 알파벳으로된 문자를 입력하는 방식)

생각보다 팀원들이 적극적으로 의견을 내고 의견이 빠르게 일치되어 게임의 방향성이 정해지게 되었습니다.

 

목표 : 2인 플레이 + 아재패턴이 적용 + 수영 게임 만들기.

 

DAY 1.

프로젝트 시작 전날 생각보다 빠르고 간결하게 의견이 일치하여 주제가 정해졌기 때문에

3명의 팀원은 각각 어떤 부분을 구현 할 것인지 각각 파트를 나누기로 하였습니다.

3명이기때문에 크게 3개의 부분으로 나누기로 하였습니다.

  • 아재패턴(로직)을 만들고 해당 UI를 작성하는 부분
  • 플레이어의 움직임(모션)을 만들고 상호작용을 구현하는 부분
  • 플레이할 맵과 배경을 만드는 부분

위처럼 3개로 크게 나누어 작업을 하기로 하였습니다.

가장먼저 아재패턴의 적용을 제안하였던 팀원은 바로 자신이 제안한 부분을 구현하기로 하였습니다.

 

저는 캐릭터가 직접움직이고 상호작용하는 부분에 욕심이 있었기 때문에 플레이어 클래스를 만들기로 하였습니다. 

 

나머지 한명의 팀원 또한 본인의 취향이 맵 제작에 맞아 각각의 역활 또한 빠르게 정해졌습니다.

 

예전 2D 때와는 다르게 좀더 체계적으로 팀프로젝트를 해보고자하는 욕심이 있었기 때문에 단순하게 역활만 끝내는 것이아닌 좀더 다양하게 배워보는 시간이 되었으면 하여 팀원끼리 일정을 공유하고 작성한 소스코드를 공유할 수 있도록 방법을 생각하였습니다.

 

다른팀에서 GitHub 를 사용하기로 한 방법을 저희도 채용하기로 하였습니다.

때문에 프로젝트 시작함과 동시에 Git & GitHub 에 대한 영상들을 찾아보고 각자 공부하며 프로젝트를 진행하기로 하였습니다.

 

그와 동시에 서로의 일정을 확인하기 위해서 일정 공유 사이트 '트렐로' 를 사용하기로 하였습니다.

첫날은 팀원들 모두 깃허브에 가입하고 트렐로에 보드를 개설하였습니다.

 

Manage Your Team’s Projects From Anywhere | Trello

Task management Use Trello to track, manage, complete, and bring tasks together like the pieces of a puzzle, and make your team’s projects a cohesive success every time.

trello.com

 

DAY 2.

프로젝트 2일째는 본격적으로 각자 구현하기로한 부분을 만들기 시작했습니다.

제가 맡은 부분은 플레이어 부분이기때문에 바로 서로 통일시킨 프레임워크에 플레이어 클래스를 만들었습니다.

 

최우선적으로 플레이어의 기본 틀이 필요하기때문에 형태를 만들기위해서 mesh 파일과 shader 파일을 적용시켜 머리 몸통 팔 다리 를 xml 형식의 파일로 제작하여 사람의 형태부터 만들었습니다.

 

xml 파일을 만들때 처음에는 각각의 관절에 중심점을 두고 무작정 제작하였으나

플레이어의 움직임을 구현시킬 때 짐벌락 현상과 애니매이션 효과를 위한 각도 보간에서 문제가 있었으므로

중심이되는 중심점들을 세세하게 우선 배치한뒤에 중심점을 기준으로 형태를 재구성 하였습니다.

 

처음에는 언리얼에 뒤쳐지지 않을 멋있는 녀석을 만들어보겠다는 의욕이있었지만.. 처음부터 형태를 만들고 애니매이션을 만드는 것은 정말정말정말 쉽지 않았습니다...

어찌저찌 해서 가장큰 기본 틀인 플레이어의 모양을 잡았습니다.


계획대로 진행되고 있지는 않은 것 같죠..?

정점을 찍고 텍스처를 맵핑하고.. 아직 단순한 도형밖에 적용 시키지 못하기 대문에

마인크래프트의 캐릭터처럼 되었습니다.

본격적인 프로젝트 첫날은 조금 좌절도 하면서 캐릭터를 만들고 모션에 사용할 플레이어의 관절부분의 각도를 저장해둘 xml 파일을 만드는 것으로 마무리가 되었습니다.

 

DAY 3.

전날 만들어둔 플레이어 클래스를 켜고 오늘은 캐릭터의 상태를 분류 하기로 하였습니다.

애니매이션을 적용시키기위해서는 플레이어의 상태를 나눠두고 그상태에서 xml파일을 사용하여 플레이어의 관절 각도를 보간 시켜줄 필요가 있었습니다.

 

우선 기본적인 플레이어의 상태를 나누었고 습니다.

  • IDLE : 게임시작전 플레이어가 물위에 둥둥 떠있으며 팔이 살짝 벌려지고 양다리가 앞뒤로 움직이는상태
  • SWIMMING : 게임이시작되고 패턴입력을 받지 않았을때 기본 수영상태
  • BOOSTER : 패턴입력이 성공하여 빠르게 수영하는 상태
  • DROWN : 패턴입력이 실패하여 물에빠져 허우적대는 상태
  • WIN : 게임종료시 먼저 도착하여 승리하였을 떄의 상태
  • LOSE : 게임종료시 도착하지 못하여 패해하였을 때의 상태

위의 6가지 상태로 분류 하게 되었습니다.

플레이어의 상태는 enum class 로 만들어두었으며 플레이어의 각 상태일때마다의 행동들은 함수의 형태로 구현하도록 하였습니다.

Actor 보다는 GameObject 에 있는것이 맞을 듯하여 이동!
플레이어 클래스의 cpp 업데이트 부분에서 스위치로 전환해주며 해당함수를 불러오는 형태입니다.

 

여기서 기본 프레임워크가 시작 프로젝트를 기준으로 메인화면(메인씬) 게임화면(씬2) 로 나뉘어지기때문에

플레이어 클래스는 상위 클래스인 Actor 를 상속받아 작성하였습니다.

이렇게 상태를 나누어 스위치를 사용하여 플레이어의 상태를 바꾸어 주고

각 상태일때 애니매이션을 불러줄 함수들을 만들었습니다.

 

플레이어 IDLE 상태

양팔은 벌어지고 다리는 앞뒤로 흔들립니다.

 

플레이어 SWIMMING 상태 ( BOOSTER 상태는 SWIMMING 상태의 애니매이션 속도를 조절)

수영하며 숨을 쉬기 위해 고개를 살짝씩 들어주고 다리는 상하운동 팔은 회전운동 합니다.

 

플레이어 DROWN 상태

물에 빠진 상태는 다리를 앞뒤로 움직이며 팔을 위로 높게 벌려 흔듭니다. 플레이어는 상하로 움직입니다.

 

플레이어 WIN & LOSE 상태

승리시 양팔을 위로올려 전방 상단의 좌우를 주시합니다. 패배시 바닥의 좌우를 주시합니다.

처음 네모네모한 캐릭터를 만들었을 때에는 너무 단순해보이고 마음에 들지 않았지만

텍스처를 맵핑한뒤 보간을 통하여 애니매이션을 만든 뒤에는 생각보다 마음에 들었습니다.

 

DAY 4.

4일차에는 팀원들과 연락하여 각각의 진행 상태를 확인하였고

아재패턴을 적용하는 팀원의 중간 결과가 나왔기때문에 플레이어 클래스에 적용해보는 날이 되었습니다.

처음에는 플레이어의 위치 바로 위에 UI를 렌더하면 될 것 같았으나 플레이어와 UI가 겹쳐 보이는 상황이 되어버려 각가 추가적으로 수정을 진행하였습니다.

위치조정은 크게 문제 가없었으나, 저는 플레이어 2 그리고 아재패턴은 2인용 게임이기때문에 키보드 위치로 플레이어1 = 영문 패턴으로, 플레이어2 = 키패드의 숫자패턴으로 맞춰야 했기 때문에 추가적인 작업이 진행 되었습니다.

 

플레이어 클래스에서 이때 문제가 발생하였는데

하나의 클래스로 단순하게 2개의 객체를 만들어 플레이어1, 플레이어2를 만들면 되겠다~ 생각했지만

그렇지 않았습니다..

xml 형식으로된 플레이어의 정보가 저장된 파일을 불러올때 플레이어에 맵핑한 이미지가 같기 때문에 두개플레이어가 모두 같은 스킨을 입고 있어 마음에 들지 않았습니다.

때문에 플레이어1에 사용했던 texture 이미지를 직접 컬러값을 수정하여 다른 스킨의 형태를 만들게 되었습니다.

위처럼 기본 플레이어와는 조금 다르게 썬탠한 듯한 구릿빛 피부의 스킨을 만들었습니다.

이렇게 플레이어2까지 완료가 된 후에 팀원들과 일정을 다시한번 조절하게 되었습니다.

 

단순한 게임인 만큼 다들 금방 끝내고 서로 코드를 합쳐 빠른시일내로 전체적인 틀을 만들수 있을 줄 알았으나 맵과 배경이 갖추어지지않아 그외에 필요한 부분들을 준비해야 했습니다.

 

아재패턴은 영문패턴 & 숫자패턴 두가지가 만들어져야했으므로 각각에 맞는 UI 이미지들이 필요했기에 추가 작업을 진행하게 되었으며

 

맵과배경 또한 아직 미완성인 상태이기때문에 이어서 진행을 하도록 하였습니다.

 

먼저 플레이어의 클래스가 완료된저는 추가적으로 필요한 메인화면(MainScene) + 게임메뉴버튼(UI) 부분이 빠르게 만들어져야 했기때문에 게임 UI 버튼을 급하게 준비하게 되었습니다.

 

DAY 5.

플레이어 클래스 완료후 인게임의 UI를 만들기위해서 필요한 UI이미지를 찾게되었습니다.

무료배포된 이미지를 몇가지 찾아서 필요없는 이미지들을 가려내고 저희팀에 필요한 느낌의 이미지 형태를 직접 만들 필요가 있었습니다.

구글링을 하던도중 게임시작 버튼의 느낌이 투박하면서도 깔끔한 픽셀느낌의 이미지를 구하게되었습니다.

무료로 배포되어 구한 위의 START 버튼의 느낌이 플레이어의 네모네모한 느낌과 너무 잘 어울려서 위의 이미지를 채택 하였습니다.

 

채택후 직접 이미지를 편집하여 아래의 PLAY PAUSE EXIT 버튼은 만들었습니다.

당일은 게임과 어울릴만한 이미지를 찾는데 생각보다 많은 시간이 소요되었고

UI의 배치구성과 마우스와의 상호작용을 생각하는데에도 상당히 많은 시간이 필요했습니다.

 

어찌저찌 생각해둔 구성대로 코드를 짜면서 문제가 한가지 발생하였는데 

게임플레이시 카메라의 구도를 어떻게 할지가 문제가 되었습니다.

 

카메라구도 1 : 플레이어1 & 2 를 한화면에 모두 담도록한다.

카메라구도 2 : 플레이어1 & 2 를 화면 반을 나누어 각각 담도록한다.

 

위의 2가지로 나뉘었는데 간단히 생각해보면 당연히 구도는 2번이 되어야 했습니다.

2인용 게임이고 패턴을 잘 맞춰서 빠르게 왕복하는 유저와 패턴을 많이 틀려 뒤쳐진 유저의 간격이 멀어질수록 화면의 중심 위치가 애매해 지기떄문입니다.

 

그런이유로 카메라 2개를 생성하여 

각각의 카메라 위치와 뷰포트 크기를 정해주었습니다.

카메라를 한개가아닌 2개의 시점을 만들어야하기때문에 모든 객체의 렌더는 Cam & Cam2 의 아래쪽에 각각 한번씩 총2번 렌더를 했습니다.

 

그렇게 카메라를 2개로 나누어 렌더구간도 나누어 주고 난 뒤에 UI를 적용하면서 또한번 문제가 발생하였습니다. 바로 UI의 위치와 마우스와의 상호작용에 의한 문제 였습니다.

 

처음에는 화면의 한가운데를 중심으로 좌우 대칭 형태의 UI를 만들고자 하였으나

카메라의 시점이 2개가 되면서 마우스와의 충돌(상호작용)이 뷰포트좌표로 인하여 차이가 나게 되었습니다.

좌표 차이 뿐만이아닌 UI의 배치에도 문제가 있었는데 UI를 배치할때는 월드 좌표가아닌 스크린좌표 + 프로그램 실행창 크기에 대비하여 비율로 위치를 잡기때문에

뷰포트가 2개로 나뉘면서 좌우에 깔끔하지 못하게 배치가 되었습니다.

 

위의 문제를 해결하기위해서 UI를 화면의 중심에 놓는 것이아닌 플레이어2의 화면측(게임화면우측) 방향에 상호작용하는 UI를 모두 몰아두고

 

미리생각해둔 일시정지시 PAUSE UI가 깜빡이는 효과는

왼쪽화면에반쪽+오른쪽화면에반쪽을 더해주어 하나의 화면의 경계없이 중심에 보이도록 하였습니다.

우측에 위치한 UI 버튼과 깜빡이는 PAUSE UI

위처럼 결정 하여 코드를 만들었고 일시정지기능은 도중에 구현하였습니다.

싱글톤으로 만들어진 Timer 클래스에서 게임은 프로그램실행후 deltaTime & deltaScaleTime 을 사용하여 시간경과를 이용하는데 이부분은 원래 private 구역에 만들어져있어 public 으로 이동시켜 시간조정을 강제적으로 조작 하여 구현해 보았습니다.

 

원래 게임과 관련하여 치명적인 오류가 될 수 있을법한 것을 public 으로 구현하는 것은 옳지 않을 수 있으나 한번 구현해 보고싶어 변경해보았습니다..

 

이렇게 일시정지 기능을 만들고난뒤 일시정지 상태일 때에 PAUSE UI가 화면의 한 가운데 깜빡이는 효과에 문제가 생기게 되었으나 위의 변수를 사용하지않는 시간을 측정하는 별도의 코드를 만들어 따로 구현하도록 하였습니다. 

 

처음에 문제가 생기고 해결방법을 찾지 못하였을때는 타협해서 깜빡이지 않는 UI를 그대로 둬야할까 했으나 문제를 해결하고나서는 많이 뿌듯했습니다.

 

DAY 6.

UI까지 구성하고 난 뒤에 팀원들과 디스코드를 통하여 서로 상태를 확인하고 GitHub데스크탑을 이용하여 코드를 합쳐 공유 했습니다.

 

처음에는 간단히 각각 클래스를 만들기로 했으니 코드만합치면 모든것이 끝날 줄 알았습니다.

하지만 아직까지 파트를 완성하지 못한 팀원도 있었고 막상 코드를 합하고 나니 생기는 문제들도 많이 있었습니다.

 

아재패턴 로직과 플레이어를 연결하면서 어느 조건에서 게임을 시작하고 끝맺으며 패턴입력과 플레이어의 상태를 연동시키는 부분에서 서로 설명하는데 많은 시간이 소요되었습니다.

 

크게 문제없이 합쳐졌으나 아직까지 완료되지 못한 맵(수영장) 부분과 게임시작전의 메인화면(MainScene)부분도 구현해야되기때문에 맵을 담당하는 팀원은 이어서 작업을 진행하였고

 

아재패턴을 담당하던 팀원은 플레이어 클래스와 합쳐 좀더 상세하게 로직을 구현하게 되었습니다.

 

저는 당일 최우선으로 급하다고 생각한 메인화면을 추가적으로 담당하게 되었습니다.

이때 당시에는 코드를 서로 공유파일에 합치면서 일부코드가 없어지거나 패치에 오류가 생기는 현상등으로 다들 정신이 없었던 것 같습니다.

 

각각 원본파일들을 따로 백업해두고 공유하였기때문에 큰 문제는 없었지만 다들 GitHub를 사용하는데  초보였기때문에 많이 힘들었습니다...

 

그렇게 정신이 없던 와중에 추가적인 씬(메인화면)을 만들었는데.. 정말 원하지 않던 퀄리티가 나와서 스스로 많이 실망했었습니다..

 

DAY 7.

약속된 마지막 날은 정말 정신이 없었던 것 같습니다.

급하게 만든 메인화면을 공유파일에 추가하고 상호작용을 넣고 마지막으로 플레이하면서 큰 버그가 없는지 몇번이고 플레이해보는과정으로 잠도 거르듯이 마감을 했습니다.

 

프로젝트를 마치면서.

짧은 1주일 간의 프로젝트는 그렇게 마무리가 되었습니다.

프로젝트를 하면서 새롭게 GitHub 라는 것을 배워가고 다른팀원들의 코딩 방식도 볼수 있어서 많은 경험을 했다고 생각합니다.

 

하지만 프로젝트를 하며 좋았던 점만 있는 건 아니었다고 생각합니다.

현재 직장인의 상태도 아니며 업무가아닌 자율적인 참여와 작업으로 이루어지기때문에 각각의 사정으로 작업을 할 수 없는팀원도 생기고 일정도 맞춰져 가지 않는 경우도 많았기 떄문에

부족한 부분을 채우기위해 많은 힘든 일이 었었다고 생각합니다.

 

플레이어를 멋있게 만들고 싶었으나 마인크래프트가 되어버리고...

계획에도 없던 부분들(UI, 카메라, 메인화면)...을 만들어야 해서 힘들기도 했지만

여러가지 만들면서 배운것도 참 많았던 것 같습니다.

D3D 만으로 처음부터 게임을 만드는게 많이 어려운 것 같다고 느꼈습니다.

 

나중에는 꼭 언리얼에 부족하지않을 D3D포폴을 만들고 싶다!

 

 

마지막으로 플레이 영상 & GitHub 입니다.

 

 

GitHub - rhksgml78/1weekproject: DirectX11 3D Programing 기초단계 처음 팀 프로젝트

DirectX11 3D Programing 기초단계 처음 팀 프로젝트. Contribute to rhksgml78/1weekproject development by creating an account on GitHub.

github.com

 

댓글