본문 바로가기
Tips

HUD Maker로 Map HUD 만들기 - RPG Maker MV

by biud436 2019. 11. 22.

HUD Maker는 인 게임 도중 화면 상에 텍스트나 게이지 등을 띄우고 드래그로 쉽게 조작할 수 있게 도와주는 에디터이며 RPG Maker MV에서 핵심 플러그인으로 부상하였다. HUD Maker를 사용하려면 SRD_SuperToolsEngine라는 플러그인이 우선적으로 필요하다.

HUD Maker는 슈퍼 툴 엔진의 추가 기능이기 때문에 플러그인을 다운로드 받은 후 플러그인 관리에서 설정할 때 우선적으로 설정하고 그 아래에 HUD Maker를 추가해야 한다. HUD Maker는 F12 버튼을 눌러 띄울 수 있고 처음에 나오는 메뉴에서 HUD Maker 버튼을 선택하면 된다. Menu Editor는 창을 이동하거나 투명도를 조절할 수 있는 에디터로 메뉴나 전투에서 상태 창을 없애거나 배틀 로그 창을 없앨 수 있는 것으로 전투에서 HUD Maker를 사용할 때 창 위치 조절을 할 때 요긴하게 사용된다.

HUD Maker 는 맵과 전투에서만 사용할 수 있다. HUD Maker는 게임이 실행되고 있는 메인 윈도우의 값을 가져오거나 값을 내보낼 수 있다. 따라서 게임 실행 도중에도 리얼하게 HUD를 편집할 수 있게 된다.

 

HUD Maker로 HUD를 완성한 모습

HUD Maker는 리소스와 약간의 자바스크립트 함수와 변수만 호출하면 어렵지 않게 할 수 있다. 리소스가 없어도 셰이프를 직사각형으로 띄우고 그라이데이션으로 전체를 채우면 기본 게이지바와 비슷한 게이지바를 만들 수 있다.

HUD Maker의 기본은 드래그로 특정 위치에 이미지를 배치하는 것부터 시작한다. 별도로 준비한 리소스가 있다면 그것을 사용하고 없으면 강좌에서 준비된 이미지를 사용하거나 Shape로 대체하도록 하자. 참고로 RPG Maker MV로 게임을 만드시는 분들이 많이 있는 공식 포럼엔 다양한 HUD Maker 용 리소스들이 공유되고 있다.

이미지를 준비하지 못한 경우, Shape 엘리먼트를 추가하면 기본 게이지바와 유사하게 만들 수 있다. HUD Maker는 \img\SumRndmDde\hud 폴더에서 HUD 리소스들을 찾는다. 따라서 상태 아이콘을 만들거나 비트맵 폰트로 숫자 아이콘을 띄우거나 HUD Maker 상에서 이용되는 모든 리소스들이 이 폴더 아래에 있어야 한다.

 

gauge_backs 폴더에 필자는 다음 리소스를 추가했다. 이 리소스는 비어있는 게이지바를 나타낸다. 붉은색 게이지바가 줄어들면 뒷 배경으로 보여지게 된다.

 

그리고 gauge_images 폴더에는 다음 이미지들을 추가하였다. 이 폴더에는 비어있는 게이지바 위를 채우는 이미지들이 위치하게 된다.

 

pictures 폴더에는 HUD의 배경 이미지를 추가한다. 이 폴더에는 전체적인 HUD의 배경을 장식하는 핵심 리소스가 오게 된다.

Create New Element에서 Picture를 선택하고 새로운 엘리먼트를 만들고, 마우스로 해당 HUD 이미지를 드래그하여 원하는 지점에 배치해보자.

 

새로운 엘리먼트를 여기서 만들 수 있다.

Image 란에서 hud_window_empty라는 방금 추가한 배경 이미지를 선택하면 된다. Image 리스트 박스는 hud/pictures 폴더에 있는 모든 PNG 이미지들을 로드하여 리스트에 추가한다.

 

Scale X를 -1로 설정하면 이미지가 좌우 반전된다.

잡다한 기능들을 설명해야 하는 지 모르겠지만 녹색으로 되어있는 Condition 부분은 조건식이 오는 부분이다. 조건 분기처럼 조건에 따라 이미지를 띄우거나 안띄울 수 있는 선택을 할 수 있다. 예를 들면 다음과 같은 조건식을 걸어주면 죽었을 때는 게이지바가 감춰지게 된다.

 

// 죽음 상태가 아닌 경우에만 이미지가 뜨게 한다.
$gameParty.leader().isDeathStateAffected() === false

 

조건식을 설명했지만 필자는 추가하지 않도록 하겠다. 필자의 HUD는 플레이어가 죽은 경우에도 계속 필드 상에 떠있어야 하기 때문이다. 다음은 Create New Element에서 Image Gauge를 선택하고 HP, MP, EXP 바를 배치하자.

Image Gauge Element에서는 Cur Value와 Max Value를 적을 수 있게 되어있다. 현재 값과 최대 값이 있으면 비율을 만들 수 있고, Sprite 객체의 setFrame 메서드를 통해 게이지바의 체력을 채우고 줄어들게 하는 것을 할 수 있게 된다.

 

Condition을 걸면 조건식이 true이어야 이미지가 뜨게 된다.

이건 기본적으로 설정되어있는 것을 그냥 쓰면 된다. 현재 체력과 최대 체력을 이용하여 비율 식이 만들어지게 된다. Scale X와 Scale Y의 경우, 좌우 반전이나 상하 반전 그리고 이미지를 확대, 축소 할 수 있는 부가적인 옵션이다. 레이어의 경우, 숫자 값이 증가할 수록 더 나중에 그려지게 된다. 즉, Z 값이 상승하면서 더 위에 보이게 된다.

 

현재 마력과 최대 마력은 mp와 mmp로 요약된다. 파티원의 리더는 첫번째 파티원을 뜻하고, 첫 번째 파티원의 현재 마력과 최대 마력으로 비율값을 구하여 게이지바를 구성하게 된다.

다음은 문제의 경험치 게이지바로 경험치 게이지바의 경우, 일반적으로 exp나 mexp 같은 속성이 없으며 누적 방식으로 되어있다. 따라서 다음 경험치 값에서 현재 경험치의 초기 값을 빼야 하는 계산이 필요하다. 그런데 최대 레벨에서는 다음 경험치 값이 없으므로 문제가 생길 수 있다. 따라서 삼항 연산자 등을 사용하여 분기를 해줘야 한다. 삼항 연산자는 자바스크립트에서 IF 문을 한 줄로 정리할 수 있는 연산자이다.

 

작성해야 할 자바스크립트가 상당히 길고 한 줄로만 작성해야 해서 짤려있다는 것을 볼 수 있다. 필자가 직접 작성했지만 필자도 텍스트 에디터의 도움을 받아 줄을 한 줄로 연결한 것이다. Note Pad++나 Visual Studio Code에 이러한 기능이 있다. 필자의 경우, RS_HUD 플러그인을 만들 때 만들어놓았던 메서드를 참고하여 경험치 게이지바를 구현하였다.

하지만 겁먹지 말자. 이를 해석할 필요는 없다. 필자가 어려운 부분은 아래에 작성해놓았으며 여러분들은 그냥 복사해서 넣어주기만 하면 된다.

EXP의 현재 EXP 값(Cur Value) 값은 다음과 같아야 한다. 즉시 실행 함수로 구현되었지만 함수에서 최종적으로 특정 문자열을 반환하게 되어있으므로 문제 없이 문자열이 출력되게 된다.

 

 

(function() { var l = $gameParty.leader(); return (l.isMaxLevel()) ? l.expForLevel(l.maxLevel()) : (l.currentExp() - l.currentLevelExp()); })();

 

최대 EXP 값(Max Value) 값은 다음과 같이 해줘야 한다. 여러가지 고려되어있기 때문에 자바스크립트가 필요 이상으로 상당히 길어진 느낌이지만 버그를 없애려면 어쩔 수가 없다.

 

(function() { var l = $gameParty.leader(); return (l.isMaxLevel()) ? l.expForLevel(l.maxLevel()) : (l.nextLevelExp() - l.currentLevelExp()); })(); 

 

수식을 채운 다음에 Refresh를 성급하게 누르지 말고, EXP 바를 적당한 위치에 우선 배치해준다. 레벨 1의 캐릭터는 초반 경험치가 0이므로 EXP 바가 화면에서 사라지게 되므로 Refresh를 누르기 전에 게이지바를 배치해야 수월하다. 필자의 경우, 원할한 테스트를 위해 경험치의 증감을 이용하여 레벨을 2까지 올려놓았다.

다음은 액터의 얼굴 이미지를 띄울 차례로 Actor Face 엘리먼트를 추가하면 된다. Actor Face 엘리먼트에는 원형 클리핑 마스크 기능과 이미지의 가로 크기(Width)와 세로 크기(Height)를 설정할 수 있는 기능이 있다. 이것으로 얼굴 이미지가 들어갈 곳에 얼굴 이미지를 추가할 수 있다.

 

레이어를 2로 설정하면 모든 이미지보다 위에 뜨게 된다. 1번 파티원의 얼굴 이미지가 기본적으로 뜨게 되므로 이렇게 완성된 이미지를 드래그하여 배치해주면 끝난다. 만일 1번 파티원의 얼굴 이미지가 아니라 다른 파티원의 얼굴 이미지를 표시하고 싶다면 다음과 같이 해야 한다.

 

 

// 두 번째 파티원의 액터 ID
$gameParty.members()[1].actorId();

 

 

텍스트 배치의 경우, Text Element를 추가하면 만들 수 있다. 폰트 설정에서 GameFont의 경우, 기본적으로 로드되는 mplus-1m-regular.ttf라는 폰트이며 나눔고딕이라고 적을 경우, 컴퓨터에 설치된 폰트를 불러오게 된다. 컴퓨터에 설치하지 않은 폰트를 폰트 폴더에서 로드하려면 YEP의 Load Custom Font 플러그인을 사용하여 커스텀 폰트를 로드를 해놓아야 한다.

 

Value 부분을 보면 ES6 기반의 자바스크립트 문자열을 사용하고 있다. ES6 기반의 문자열에선 스크립트를 루비처럼 삽입할 수 있다는 것이 특징이다. 따라서 다음과 같이 작성해야 한다. HP와 MP는 게이지바 설정 할 때와 별 다를 게 없이 첫 번째 파티원의 현재 체력과 최대 체력 값을 문자열로 반환하게 된다.

 

 

${$gameParty.leader().hp} / ${$gameParty.leader().mhp}

 

 

MP도 마찬가지로 Text Element를 생성하고 적당한 위치에 배치한 후, Value 값을 수정해준다. HP 설정과 한 글자만 다르다.

 

HP에서 MP로 변경되었다. 이 외의 차이점은 없다. 자바스크립트 ES6에서는 ${} 안에 자바스크립트를 적으면 자바스크립트 문자열로 자동으로 변환된다.

 

${$gameParty.leader().mp} / ${$gameParty.leader().mmp}

 

다음은 EXP 게이지바 부분이다. HUD의 하이라이트라고 할 수도 있는데 사실상 이 강좌에서 제일 복잡한 부분이다.

 

EXP바의 Value 부분은 다음과 같다. 문자열 형식인데다가 한 줄로만 작성이 가능해서 가독성이 다소 크게 떨어진다. 하지만 여러분들이 신경 쓸 필요는 없다. 필자가 어려운 부분은 대신 구현하였다. 다음 수식은 현재 EXP와 최대 EXP를 구하여 문자열로 반환한다.

 

${($gameParty.leader().isMaxLevel()) ? $gameParty.leader().expForLevel($gameParty.leader().maxLevel()) : ($gameParty.leader().currentExp() - $gameParty.leader().currentLevelExp())} / ${($gameParty.leader().isMaxLevel()) ? $gameParty.leader().expForLevel($gameParty.leader().maxLevel()) : ($gameParty.leader().nextLevelExp() - $gameParty.leader().currentLevelExp())}

 

최종적으로 완성된 이미지는 다음과 같다.

 

여기까지 따라해보면 폰트가 필자와는 다르다는 것을 알 수 있다. 필자의 폰트도 기본 폰트인 GameFont로 설정되어있다. 하지만 필자의 경우 GameFont의 전신 부분인 font 폴더의 gamefont.css 자체를 수정하여 다른 폰트를 로드하게 만들었다. 쉽게 말하면 기본 폰트인 mplus-1m-regular.ttf 파일대신 neodgm.ttf라는 도트 폰트 파일을 사용하였기 때문에 폰트가 달라진 것이다.