Inv 오브젝트의 스텝 이벤트 내용에 대해서 설명을 시작해봅시다.
우선 최상단에 enable 이 false일 때 아예 exit를 합니다.
exit의 경우 이벤트나 문 자체를 나가버리기 때문에 강려크하면서도 유용합니다.
특히 이렇게 활성화 여부를 아예 전체 이벤트에 거는 경우 최상단에 exit를 박아두기도 합니다.
그리고 전에도 한번 간략히 설명했던 드래그 이동 관련 내용이 담긴 파트가 있는데, 보시면
if ui_drag==1 {} else{} 이 부분이 드래그의 메인 파트인 걸 알 수 있죠?
그리고 점차 다른 인스턴스들을 만들면서 그 설정 조건을 덧씌웠다 보시면 됩니다.
이 윗 부분은 다른 인스턴스들을 다루면서 하게 되니 일단 다음에 다루도록 하겠습니다.
inv_arrange()라는 스크립트 혹은 펑션이 호출되네요?
그런데 어딘가 익숙하지 않습니까?
네. <Create>이벤트에서 보았던 바로 그 녀석이군요.
펑션을 오브젝트 자체에서 선언하고 쓸 수 있다는 건 이렇게 편리합니다.
이런 내용을 적어놓고, 실제 쓰이는 <Step>이벤트나 다른 이벤트에서는 함수를 호출하기만 하면 되므로
훨씬 깔끔하고 보기도 좋거든요.
그 다음은 p와 관련된 내용들이네요.
paging을 어떻게 할 지에 대해서, 최소값과 최대값 세팅을 해놓았군요.
이 통으로 페이징과 관련이 되어 있다고 볼 수 있습니다.
device_mouse_4는 쉽게 말해 x1,y1,x2,y2 순으로 파라미터를 받아서 마우스의 x,y가 x1보다는 크고 x2보다 작고, y1보다는 크고 y2보다는 작은 위치에 속해있는지를 반환하는 스크립트입니다.
클릭하는 마우스의 위치가 아예 오버된 경우 p의 값을 양 극단으로 이동시키고, 이 값이 위의 최소값 최대값에 걸리므로 그에 맞게 조정됩니다.
반면 클릭하는 마우스의 위치가 페이지 1, 페이지2, 페이지3에 해당하는 마크의 위치에 해당할 경우 페이지 변수의 값을 그에 맞게 각각 0, 1, 2로 부여합니다.
자, 이제 우리가 살펴봐야할 if 문이 있는데요, item_drag인지 아닌지 여부를 체크합니다.
이 파트가 굉장히 중요합니다. 쭉 내려가야 끝이 납니다.
축약을 해보아도 그에 상응하는 else문이 한 157 라인 쯤에서 등장하네요.
압축해서, 크게 메인 파트를 나누어보면, item_drag가 참일 때, 아닐 때 각각 1파트씩 2파트, 그리고 아래 각각 1파트 씩으로 구성되어 있다고 보실 수 있겠습니다.
아래 파트를 보면, mb_none일 때와 관련이 있네요.
자세히 보니 mb_none일 때, 마우스가 슬롯에 위치하는 경우를 반환하고 있습니다.
slot_size_width, slot_size_height는 미리 설정해둔 슬롯의 크기를 반환합니다.
Arm의 show_item_detail을 비활성화하는 걸로 보아 show_item_detail과 관련있는 파트임을 짐작해볼 수 있습니다.
그렇습니다. 마우스를 가만히 가져다두고 있다보면 아이템의 정보가 뜨도록 하는거죠.
다시 맨 위로 돌아와 봅시다.
주석을 제가 다 달아 놓았습니다.
다른 카테고리를 누르면 드래그하고 있는 아이템을 돌려보내는 파트라고 기록이 되어있습니다.
즉, 무기, 소비, 기타, 캐시 고르는 칸이 있다고 전에 말씀드렸죠? 이를 누르면 마우스로 끌어당겨서 옮기고 있는
아이템도 원래의 위치로 돌아가고, 가령 무기를 고르다가 소비를 누르면 무기 아이템창이 아닌 소비 아이템창이 나와야
유저 입장에서 더 편하겠죠? 또한 혼동 면에서도 무기 오브젝트가 소비 오브젝트로 이동된다거나 하는 오류를 막기 위해서도 아이템을 원위치 시켜주는 과정이 꼭 필요할 겁니다.
아래로 내려가면, 인벤토리에서 아이템을 하나 선택하여 드래그하는 파트가 나옵니다.
즉 이것이 item_drag가 true인 상태에서 인벤토리에서 아이템을 골라서 드래그하는 상태인 경우가 되겠죠.
이 파트도 내용이 꽤 깁니다. 쭉 내려보면
거의 item_drag의 끝 파트에 가까운 정도의 규모를 보여줍니다. 바로 직전의 엔드 블록이라고 할 수 있죠.
바로 아래 엔드 블록이 if (item_drag = true) {} 를 닫아주는 엔드블록입니다.
줄여놓아서 더 보시기 편하겠지만 바로 아래에 해당하는 내용에 상응하는 else문(item_drag==false)이 있죠.
별표도 한 번 찍어봤습니다. 이게 되네요.
아무튼, 위로 올라와서 보면, 이를 최대한 필요한 부분만 남기고 축약해서 한 눈에 살피자면 이와 같습니다.
크게 이것도 3 덩어리로 되어있음을 아실 수 있습니다.
즉 inv 자체 안에서의 마우스 이동과 관련된 파트, Arm(아머창)과 연동된 파트, Quick Slot과 연동된 파트로 나뉘어져 있습니다. 이렇게 전체적인 틀을 파악하는 게 중요합니다.
우선은 다시 돌아와서 item_drag의 파트는 그럼 [카테고리 위에 커서 ] 파트, [인벤토리에서 아이템 드래그] 큰 파트로 나뉘고, 아까 본 건 [인벤토리에서 아이템 드래그] 파트도 다시 나누면 3파트로 나뉜다는 걸 확인한 거였죠?
이번에는 [카테고리 위에 커서] 파트 부터 살펴보겠습니다.
무기 일경우, 여러가지 타입이 존재하기에 ||을 통해서 동시에 체크를 해줍니다.
나머지는 각각에 정해진 타입을 체크를 해줍니다.
아, 그리고 이건 제가 한동안 연구했던 코드 정리법 중 하나인데, '비주얼적으로 정리하는데 집착'할 때의 방식입니다.
이렇게 하면 명확하게 코드가 어디에 속해있는지 보기 편해서 좋습니다. 장점은 10년이 지나도 보기 좋다는 거구요,
단점은 시간 소모가 커질수도 있다는 건데요, 원칙에 대해 간단히 설명을 드리자면
for문이나 if문등 '문'에 해당하고 블럭을 소환하는 이상 꼭 같은 위치로 바로 다음 아래 칸에 스타트블럭을 배치합니다.
그리고 다시 그 안에 중첩되는 '문'들의 경우 무조건 그 스타트블럭 기준으로 4칸 이상 띄어서 내부에 확실히 들어가게 합니다. 그 '문도 바로 다음 아래칸에 스타트 블럭을 배치합니다. 엔드블럭은 맨 끝에 붙여도 되지만 왠만한 경우 스타트블록과 동일한 위치에 배치합니다.
이러면 그냥 위치만으로 문들의 위계가 바로 눈에 띄어서 좋긴 한데요, 또 나중에 가져다 쓰거나 고칠 때에도 좋습니다.
문제는 이것 자체가 시간 소모가 좀 클 수도 있으니 유념하시기 바랍니다. 하지만 한 번 해두면 오래 가는 'Art'중 하나입니다.
다음 파트로 넘어가봅시다.
device_mouse_decentralized 함수는, x1,y1, width 사이즈, height사이즈를 파라미터로 부여받아서 x1,y1을 origin으로 width, height만큼의 영역에 존재하는 지 반환합니다. 이 때 origin은 중심이 아닙니다. decentralized라고 명명한 그 이유가 여기에 있습니다. 약간 0,0을 origin으로 해서 가로 세로 를 드로우할 때의 느낌을 아시죠? 그런 느낌으로 이 지점 '부터' 가로로(우측으로) slot_width만큼, 세로로(아래로) slot_height만큼의 영역에 해당하는 지를 반환합니다.
그 영역에 해당한다면, 카테고리가 무기이냐 아니냐에 따라 각각의 대처방식이 달라집니다.
인벤토리에서 아이템을 선택하는 것에 우리가 포커스를 두고 싶은데 문제는 이미 armor창에서 무언가를 선택하고 있어서 위치가 겹치는 경우가 있겠죠? 특히 무기의 경우 오류가 생길 가능성이 높습니다. 그래서 그 경우를 배제하고 자유로운 경우를 가지고 우리가 고려를 해봅시다.
pocket이라는 3차 배열에서 축을 각각 z, x, y로 생각을 해본다면 [ z ][ x ][ y ] 입니다. 이경우 우리가 z를 카테고리와 관련하여 설정한다고 했죠. 따라서 위치를 체크할 때도 마찬가지입니다. 카테고리를 설정하는 변수가 selectN이라고 했었고, paging을 우리가 설정하였고 그 page를 우리가 관할하도록 설정한 변수가 p입니다. 저희가 이 값이 원래의 selectN이 0,1,2,3, 순회하던걸 여러 페이지하에서 순환하도록 할 거라고 했습니다. 따라서 이 z축을 우리가 체크할 때 selectN+4*p으로 수식이 정의가 됩니다.
3페이지인데 왜 4p냐? 이렇게 물으신다면, 사고 회로에 잘못 접근하셔서 그렇습니다. p는 맥스인 p_max가 3인겁니다.
0, 1, 2에서 순환하죠. 그것이랑 관계없이 selectN의 순환을 우리가 표현하고자 하는 겁니다. 이 때 p가 하나씩 넘어갈 때마다 우리의 인벤토리는 동일한 카테고리의 값을 보여주되 페이지가 넘어가는 겁니다. 따라서 우리는
0,1,2,3, p:0
0,1,2,3, p:1
0,1,2,3 p:2
이런 순환을 나타내고자 하는 거죠.
이 유기성을 수학적으로 표기하기 위해 p가 1이 추가될 때 4를 더해주는 겁니다. 그러면
0,1,2,3 p:0
4,5,6,7 p:1
8,9,10,11 p:2
이런 구조가 되는 거죠. 이를 우리는 selectN + 4*p로 나타낸 것입니다.
아무튼 그래서 포켓의 위치를 순환하면서 체크할 수 있는 수식을 우리가 알아냈습니다. 그러면 어떻게 해야할까요?
일단 지금 select가 되어있는지 확인하고 아닌 경우 select를 참으로 바꿔주도록 합시다.
그리고 select_item이라는 변수에 select한 아이템의 값을 복사하고,
select_item_x, select_item_y라는 변수에 해당 item을 가져온 포켓에서의 x축 y축값을 기록해줍시다.
나중에 쓰일 일이 있을 겁니다. 지금 생각해보니 이것도 구조체로 더 간략화 시킬 수도 있겠군요.
그러고는 해당 포켓에 있는 값을 지워줍시다.
소비, 기타, 캐시 카테고리의 경우에도 무기의 특수적인 성격(아머창과의 연동)만 빼놓으면 메인 디쉬는 똑같습니다.
따라서 같은 내용을 입력해줍시다.
그 다음 아래로 내려와 볼까요?
이 파트 전체가 아머창과 관련 있는 파트입니다.
아까 볼 때는 무시무시했는데 하나씩 격파하면서 내려오니까 별 거 없죠?
Arm이 활성화되어있는 지 체크하고, Armor창에 마우스가 위치한 지 확인을 합니다.
device_mouse_y_centralized는 y만 중점으로 체크해서 확인한다는 함수입니다. 아까의 device_mouse_decentralized와 달리, device_mouse_y_centralized는 부여받은 파라미터 y1을 중심으로 하여 위아래로 부여받은 파라미터만큼의(여기서는 위아래로 146 - 즉 total height 292) 영역에 속하는 지 체크합니다. x축으로는 decentralized와 비슷하게 x1에서 x1에 부여된 값을 추가한 만큼의 위치를 체크합니다.
여기서 Arm.si는 아머창에서 마우스로 select된 위치를 의미합니다. 아머창의 경우 위치가 조금씩 다르게 설정이 될 수 밖에 없고 따라서 일률적으로 for문으로 돌리기에 어려워서 따로 떼서 체킹을 해야하는 경우도 있습니다.
마무리로 그렇지 않은 경우에는 Arm.si를 noone으로 설정합니다.
'< 프로그래밍 강좌 정리 > > 내 강좌 [ 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 - 3화 (0) | 2022.03.12 |
RPG Framework with Game Maker 2.3 - 2화 (0) | 2022.02.26 |
RPG Framework with Game Maker 2.3 - 1화 (0) | 2022.02.22 |