먼저 설명하기 전에 살펴보면, 일단 언급한 대로 시초는 Inventory 개념의 확장이었기 때문에
Inventory와 관련된 오브젝트 위주로 살펴봐야겠네요. 저같은 경우 앞 글자만 따서 Inv라 이름 지었습니다.
살펴보니 Parent 오브젝트가 있죠? Parent 로 o_gui가 지정이 되어 있습니다.
이름부터 짐작이 오긴 하지만 대충 어떤 건가 하고 들어가서 확인을 해봅시다.
생성 시 자기자신이 어떤 UI이냐에 따라 my_id가 달리 선언이 되는 군요.
image_index의 경우 사실 현재는 별 필요가 없는데 아무튼 설정이 되어있습니다.
my_pos라는 변수를, global.master_stack이라는 리스트에서 my_id의 값이 해당하는 위치를 가져오고,
그걸 기준으로 depth를 설정하는군요.
보다보니 ui_refresh(); 가 호출되는 데 이건 뭐하는 스크립트일까요?
들어가서 보니 어디서 본 녀석이 있군요.
네, 아까 보셨던 o_gui에서 뎁스를 설정하는 방식입니다.
복사+ 붙여넣기를 해서 공용으로 사용할 수 있는 스크립트로 만들고는,
o_gui에도 그대로 남겨놔서 중복 입력된 상태인 걸 알 수 있습니다.
이 경우에는 2번 설정이 되더라도 문제가 없지만 이렇게 깜빡하는 경우가 있기 때문에 주의를 해주셔야합니다.
뭔가 원형이나 아이디어 가닥을 유지하고 싶다, 이러면 //으로 주석 처리하셔도 됩니다.
휘하에 Children 오브젝트로 스탯창, 스킬창, 퀘스트창, 장비창, 인벤토리창이 있네요.
공통의 gui 특성을 두고 이를 상속 받는 개념이 되겠습니다.
그러면 global.master_stack 리스트는 대체 뭘까? 하는 의문이 드실 겁니다.
한번 살펴보러 갑시다.
아마 o_gui보다 먼저 생성되는 오브젝트들에서 선언이 되었을 거라 유추할 수 있습니다.
그 중 o_master로 올라가서 속성을 확인해보자, 바로 생성 이벤트 첫줄에 뜹니다.
코드 에디터를 잘 보기 위해서 에셋 브라우저를 잠시 오른쪽으로 치워놨습니다.
보아하니 구조가 o_gui 간의 뎁스를 설정하기 위한 리스트로군요.
생성 이벤트 중에서 repeat문을 보시면 o_gui를 생성하며 리스트에 그 뎁스 값을 기록하는 구조입니다.
키보드 <E> 키는 아머창이 뜨도록 설정되어 있군요. 비가시화 상태는 가시화를 시키고,
없으면 생성하도록 되어 있습니다. 글로벌 변수 master_stack에다가 위치를 0으로 넣죠?
그것은 다시 눌러서 뜰 경우 다른 o_gui의 뎁스에 가리지 않고, 가장 앞으로 뜨도록 하기 위함입니다.
값을 0으로 넣는 이유는 앞서 o_gui에서 살펴보았듯 Arm의 my_id로 설정하고 싶은 값은 0이었기 때문입니다.
다른 ui는 각자 자신의 my_id값을 값으로 넣으면 됩니다.
<I>키로 인벤토리를 가시화/비가시화 혹은 없을 시 생성
<K>키로 스킬창, <S>키로 스탯창, <Q>로 퀘스트창을 대상으로 동일한 작업을 수행합니다.
<삭제>이벤트에서는 선언되었던 글로벌 변수 master_stack을 파기하는 함수가 선언되었습니다.
그런데 사실 이름이 stack일 뿐 list이기 때문에 ds_list_destroy가 되어야 해요. stack 개념에서 창안해서 만들긴 했지만,
위치 값을 받아오는 것도 필요해서 list로 바꾸었습니다. 대신 위치값을 받아올 때를 제외하고는 개념적으로, stack처럼 주로 사용하는 list가 되겠습니다.
자, 그럼 Inv로 돌아와서, ui와 관련된 스크립트 위주로 살펴보면,
<End Step>이벤트에서 몇 개의 구절이 눈에 띄네요.
ui_left_press(), ui_right_press()라는 스크립트를 사용하고 있죠?
이게 어떤 스크립트인지 살펴봅시다.
우선 ui_right_press를 살펴봅시다.
이 스크립트는 사실 마우스에서 특정 위치에 있을 때 오른 버튼을 누르면 꺼지도록 할 때 선언되곤 합니다.
보시면 my_pos가 0인 경우( 맨 앞에 위치한 경우), global.master_stack 리스트에 담겨있는 값들 중 my_pos에 위치한 값을 지우고, 다시 ui_refresh();를 선언합니다. ui_refresh의 경우 my_id의 global.master_stack상 위치 값을 받아서 그걸 my_pos로 설정하고 depth로 지정하는 스크립트였죠? 그런데 이미 my_id라는 값 자체가 리스트에서 지워졌습니다. 앞서 그렇다면 my_pos는 자연적으로 -1이 되고 depth도 -1이 됩니다. 그 상황에서 visible은 false, enable은 false로 만들어 사용하지 않는 상태로 되돌립니다.
그러나 my_pos가 0이 아닌 경우 어떻게 해야할까요? my_pos가 0인 경우는 현재 선택중인 ui라는 뜻이 됩니다. 즉 열려있는 여러 ui중에서도 가장 최상단에 있는, 지금 사용하려는 ui라는 뜻이죠. 그러나 아닌 경우에, 클릭을 한 거라면 최상단으로 띄워주도록 합니다. 이러한 작업이 ui_left_press라는 스크립트에서 이뤄지기 때문에 그렇구나라고만 일단 이해하세요. 그러면 최상단으로 띄운다음 자연 my_pos가 0이 되기 때문에 자연히 '언제나' 마우스 오른쪽 버튼을 누르면 꺼지게 됩니다. 이렇게 분리해서 시행하는 이유는 my_pos가 0이 아닌 경우 자연스럽게 최상단으로 띄우고 꺼지는 flow를 연결하기 위해서였습니다.
그러면 ui_left_press를 살펴봅시다. scr_ui 폴더에 담긴 스크립트 중 마지막 녀석이군요.
이 녀석은 과연 어떤 구조일까요?
my_pos의 값을 my_id가 global.master_stack 리스트에서 위치한 값에 따라서 설정을 합니다.
즉 이 my_pos의 경우 gui 오브젝트가 위에 덮여있는지 아래 깔려있는지를 나타내는 데이터를 리스트의 위치에 넣어서,
그걸 반환하는 값이라고 보시면 됩니다.
my_pos를 알아냈으니 이번에는 ui_left_press() 스크립트의 목적인 최상단에 놓인 o_gui로 끌어올려보도록 합시다.
우선 global.master_stack에서 my_pos에 위치한 기존의 값을 삭제해줍니다.
그리고 my_id값을 최상단인 0 위치에 넣어줍니다.
여기서 최상단을 0으로 지정한 이유는 gui가 안 사용될때는 -1, 사용될 때는 0에서 5까지 서로 순환되기를 원했기 때문입니다. 올라간다고 -값으로 계속 마이너스되는 방식을 택했다면, 비효율적입니다. 또한 현재는 인스턴스 레이어 값마다 depth값이 지정되어 있고, depth의 폭이 지정되어 있습니다. 특정 값 이하로 내려가면 드로우 자체를 안 하는 케이스가 발생합니다. 그래서 0-5에서 순환하는 인스턴스가 되도록 설정했습니다.
그리고 my_id가 리스트상 0의 위치에 들어가니 my_pos는 0으로 설정해줍니다.
그리고 ui_refresh(); 함수를 통해 my_pos에 따른 depth로 바꾸어줍니다. 이 경우 0이 되겠습니다.
후.. 사실 그렇게 오래 걸리지는 않는데 제 발음상의 문제랑, 그리고 약간 두려움? 같은 거 때문에 시간이 오래 걸리는 것 같습니다. 사실 글을 먼저 적고 강좌를 할 필요도 없긴 한데, 막상 발음도 물리고 긴장되면 헛소리도 많이 하는 것 같아서 글로 정리해봅니다. 글로 정리할 때는 꽤 시간이 걸리긴 하네요. 이런 공포심? 같은 걸 잘 이겨내고 발성/ 발음 물리는 것만 좀 고쳐서 영상으로 바로 바로 찍는 게 답인 것 같네요.
'< 프로그래밍 강좌 정리 > > 내 강좌 [ GMS2 와 Unity ]' 카테고리의 다른 글
겜스 2.3으로 RPG UI 만들기 - 6강 (0) | 2022.04.10 |
---|---|
게임메이커 스튜디오 2.3으로 rpg framework 개발하기 - 5화 (0) | 2022.04.02 |
Rpg framework with Game Maker 2.3 -4화 (0) | 2022.03.20 |
RPG Framework with Game Maker 2.3 - 3화 (0) | 2022.03.12 |
RPG Framework with Game Maker 2.3 - 1화 (0) | 2022.02.22 |