[DirectX 11] Dx11를 이용한 모모도라 모작
Updated:
1. 게임의 개요
게임: 모모도라: 달 아래의 진혼곡 모작 DirectX 11 컨버팅
인원: 개인
기간: 3주
2. 게임 시스템
Core 와 Sample 클래스
[그림 1-1] : Core 와 Sample의 클래스 다이어그램
Device는 DirectX를 사용하기 위해 기본적인 장치들을 생성하는 클래스로, 이를 윈도우를 띄우는 wClass가 상속하는 구조로 되어있다.
이를 다시 Core 클래스가 상속하는데, Core에서는 게임에 사용되는 전반적인 클래스들을 초기화 한다. Filepath 클래스는 게임에 쓰이는 리소스들의 경로를 저장하는데 쓰이는데, 함수와 멤버 모두 정적으로 구성되어있다.
SpriteMgr와 FSMMgr는 각각 Sprite 와 FSM을 초기에 데이터를 저장하여 필요할 때 불러올 수 있도록 구성하였다.
DirectWrite는 화면에 문자를 출력하기 위한 클래스인데, 현재는 FPS와 게임시간 SPF를 출력하는 용도로만 사용하고 있다.
Timer는 게임의 시간에 관련된 부분들을 계산하는 클래스로, 위에서 말한 FPS와 게임시간 SPF를 Timer에서 계산을 한다. Sound는 게임에서 쓰는 사운드들을 출력하기 위한 클래스로 게임내에서 배경음과 효과음을 따로 조절하기 위해 채널과 사운드를 배경과 효과음 따로 나눠서 저장하고 있다.
DirectInput은 키의 입력을 받아 처리하는 클래스인데, 키의 입력을 홀드상태와 업상태를 구분하기 위해서 현재의 키 상태와 이전 프레임의 키 상태를 저장한다.
Frame을 호출한 뒤에 코어에 마지막에 PostFrame을 호출해서 현재 상태를 이전 상태에 저장하는 방식이다.
Sample은 이 Core를 상속하는 클래스로, 내부에서 SceneMgr 프레임과 렌더를 호출해서 게임이 진행이 된다.
[그림 1-2] : Core의 시퀀스 다이어그램
SceneMgr와 Scene 클래스
SceneMgr는 Scene을 멤버로 둬서 현재의 Scene의 Frame과 Render를 호출한다. Scene의 전환이 일어나면 현재의 Scene을 Release한 뒤, getScene함수를 통해서 바뀌는 Scene을 생성해서 다시 Frame과 Render를 호출한다. Scene은 생성을 할 때, 오브젝트들을 생성해서 배치 한 뒤, ObjectMgr에 추가하여 ObjectMgr의 Frame과 Render를 호출한다.
[그림 1-3] : Scene과 SceneMgr의 클래스 다이어그램
게임 진행중에 지나온 Scene도 다시 돌아갈 수 있게끔, GameScene은 추가적으로 InverseInit 함수를 재정의하게 하여, 플레이어가 뒤 Scene에서 앞 Scene으로 올 때에는 오브젝트를 반대로 배치할 수 있도록 하였다.
[그림 1-4] : Scene과 SceneMgr의 시퀀스 다이어그램
Shader와 Texture 클래스
[그림 1-5] : Shader와 Texture의 클래스 다이어그램
Shader와 Texture는 모두 매니저 클래스를 통해 관리하며, 매니저의 Load함수를 호출하면 우선 사용자가 원하는 데이터가 캐시에 있는지 확인을 한다. 있으면 바로 그 데이터를 반환하고, 없을 경우는 전체 데이터를 통해서 똑같은 작업을 한다. 전체데이터에도 없으면 만들어서 반환하는 구조로 되어있다.
[그림 1-6] : ShaderMgr과 TextureMgr의 시퀀스 다이어그램
ObjectMgr과 Object 클래스
[그림 1-7] : ObjectMgr과 Object의 클래스 다이어그램
Basic_Object는 오브젝트 생성시에 필요한 기본적인 버퍼 등을 가지고 있는 클래스로, Object는 이 Basic_Object를 멤버로 가진다. Object는 상수 버퍼를 사용하기위한 구조체와 정점들을 STL 벡터에 보관하며 충돌체크를 위한 충돌크기와 센터위치 값을 가진다. Plane_Object는 정점 4개로 사각형을 출력하기 위한 클래스로 이를 위해 정점의 인덱스들을 벡터에 저장하게 하였다. ObjectMgr은 오브젝트들을 관리하기 위한 클래스로 Plane_Object를 상속받는 클래스별로 따로 관리를 한다. ObjectMgr엔 컨테이너를 순회하며 Frame과 Render를 호출하는 함수가 템플릿으로 정의를 해서, 각각 컨테이너별로 따로 Frame과 Render를 호출한다.
[그림 1-8] : ObjectMgr의 시퀀스 다이어그램
Effect클래스
[그림 1-9] : Effect의 클래스 다이어그램
PlayerEffect는 플레이어의 공격에 관련된 이펙트가 있다. 근접공격 3단계와 공중 공격, 화살이펙트가 이 클래스를 상속한다. Misc는 플레이어의 버프효과를 나타내기 위한 클래스로 MiscSet은 이 Misc클래스를 배열로 둬서 하나의 세트를 구성한다. 현재 구현되 있는 아이템인 수정꽃을 사용하면 플레이어의 주위에 4개의 이펙트가 돌아다니게 되는데, 이를 통해 버프의 지속시간을 확인할 수 있게하였다.
Character 클래스
[그림 1-10] : Character의 클래스 다이어그램
Character는 State 클래스와 함께 사용이 된다. State클래스는 캐릭터의 상태를 구현하는 클래스로 캐릭터의 이동이나 점프 공격 등 모든 상태를 구현하고 그 상태를 통해서 행동을 제약하는 방식으로 구성이 돼있다. Character는 자신의 모든 상태를 STL map에 저장하고 있다. State와 Character는 상호 참조 가능한 형태로, 만약 현재 상태에서 다른 상태로의 변화가 발생하면 State는 Character의 setState로 현재의 상태를 변경 시키고, Character는 해당하는 상태로 현재상태를 바꾸고 계속해서 Frame과 Render를 호출하는 방식이다.
[그림 1-11] : Character의 시퀀스 다이어그램
State
[그림 1-12]: State의 클래스 다이어그램
State는 EnemyState와 PlayerState로 나뉘어져있다.
PlayerState
플레이어의 상태는 키보드 입력키에 의해 변하게 된다. 방향키로 이동을 하고 A키로 점프, S키로 근접공격, D키로 활공격을 할 수 있다. 실제 원작 게임에선 플레이어의 상태가 42개가 구현되어 있으나, 현재까지는 22개의 상태가 구현이 되어있다.
EnemyState
[그림 1-13]: EnemyState의 클래스 다이어그램
키보드로 상태가 변하는 플레이어와 달리 적 같은 경우는 상태별로 이벤트 발생 시 변경될 상태가 정의되어 있는 FSM이 필요하다.
[그림 1-14]: 스크립트로 저장한 FSM
적들은 생성시에 FSMMgr을 통해서 하나의 FSM을 받아서 그 FSM에 맞게 행동을 한다. 이벤트가 발생하면 FinateStateMachine의 StateTransition 함수를 호출해서 반환되는 상태값으로 변경이 되는 방식이다. 그림 2-18을 예로들어서 현재 적이 Move 상태 일 때 플레이어를 발견해서 FINDTARGET이 발생하면 플레이어를 추적하는 Chase 상태가 된다.
현재 게임에서 구현 되어있는 FSM은 한 종류로 다음과 같다.
[그림 1-15] : 몬스터 FSM
UI
[그림 1-16] : UI의 클래스 다이어그램
UI는 기본 구성요소들과 그 기본 구성요소들을 합하여 하나의 완성된 UI인 Menu 클래스 두 종류로 나눌 수 있다.
LobbyMenu
[그림 1-17] : LobbyMenu
로비 메뉴는 6개의 Bar와 1개의 Select Bar로 이루어져 있다. 방향키 위, 아래 버튼을 누르면 활성화된 슬롯이 바뀌는 방식으로 작동한다.
Setting
[그림 1-18] : 설정 화면
설정화면은 3개의 Bar와 1개의 SelectBar 그리고 2개의 ProgressBar로 이루어져 있다. 로비와 마찬가지로 위, 아래 키로 슬롯을 이동할 수 있으며, 추가적으로 효과음과 음악에 커서가 위치하면 화살표 좌, 우 키를 통해 볼륨을 조절할 수 있는데, 줄이게 되면 오른쪽에 바가 작아지고 키우게 되면 바가 커지는 형식으로 만들어져 있다.
GameUI
[그림 1-19] : GameUI
GameUI는 3개의 Bar와 1개의 ProgressBar와 한 개의 ItemSlot, 4개의 폰트로 제작하였다.
GameUI는 게임이 진행되는 동안 항상 왼쪽 위 모서리에 고정된 상태로 출력이 되며, 왼쪽 끝에 있는 아이템 슬롯은 현재 퀵슬롯에 등록된 아이템의 아이콘과 해당 아이템의 개수를 보여준다. 또한 퀵슬롯에 다른 아이템이 등록되어 있다면, E키를 통해서 언제든지 다음 아이템으로 전환할 수도 있다. HP바는 플레이어의 HP가 최대치일때는 그림과 같이 바가 가득 찬 상태로 있고, HP가 줄어들면 바의 크기도 같이 줄어들게 된다.
그 아래의 숫자 3개는 게임상 화폐를 보여주는 UI인데, 현재까지는 구현은 되어있지 않다.
InGameMenu
[그림 1-20] : InGameMenu
인게임메뉴는 게임 진행중 왼쪽 Shift키를 통해 열 수 있다. 배경에 쓰이는 Bar 2개와 Button 5개, 버튼에 해당하는 메뉴설명인 Font로 구현을 하였다.
화살표 좌, 우 키로 이동하고 원하는 메뉴에서 A키를 누르면 넘어가게 되는데, 처음부터 장비, 중요아이템, 지도, 설정, 메인메뉴로 돌아가기 순으로 되어있다.
현재 지도는 구현이 되어있지 않다.
Inventory와 Item
[그림 1-21] : Inventory
Item은 소모성 아이템과 장비아이템으로 나눌 수 있다. 활성 슬롯 밑에 있는 슬롯3칸은 퀵슬롯으로 소모성 아이템 같은 경우는 이곳에 등록을 한 뒤 게임에서 등록된 다른 아이템으로 바꿔가면서 사용할 수 있다. 지속 슬롯 밑 2칸은 장비 아이템을 등록하는 슬롯이다.
인벤토리는 소모성 아이템과 장비 아이템을 따로 저장하여 관리하며, 그로 인해 활성 슬롯에 커서가 올라가 있으면 인벤토리 내 소모성 아이템만 출력이 되게 하고, 지속 슬롯에 커서가 올라가게 되면 장비 아이템만 출력이 된다. 인벤토리에서 아이템을 빼서 퀵슬롯에 등록하게 되면 아이템은 인벤토리에서 삭제되고 퀵슬롯으로 옮겨가게 된다. 아이템을 저장하는 곳이 두 곳인 셈이다. 플레이어의 슬롯에 등록된 아이템은 언제든지 다시 인벤토리로 옮길 수 있는데 해제하고 싶은 아이템 커서에다 A키를 누르면 커서가 인벤토리로 옮겨지는데, 아이템을 바꾸고 싶다면 바꾸고 싶은 아이템으로 커서를 옮겨 A키를 누르고 장착해제하고 싶다면 None에다 두고 A키를 누르면 된다. 퀵슬롯에서 아이템을 해제하면 반대로 퀵슬롯에서 인벤토리로 아이템이 넘어가게된다. 인벤토리는 아이템이 들어올 때 정렬을 하게 되는데, 각 아이템은 고유의 ID값이 존재하고 인벤토리 내에서는 이 ID값을 기준으로 정렬을 한다.